mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-29 10:16:32 +02:00
Add pt-br locale (#261)
This commit is contained in:
parent
0b156fabe6
commit
1ef15682ea
9 changed files with 226 additions and 18 deletions
|
@ -3,7 +3,7 @@ const path = require("path");
|
|||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: "en",
|
||||
locales: ["en", "es", "de", "fr", "sv"],
|
||||
locales: ["en", "es", "de", "fr", "sv", "pt-BR"],
|
||||
localePath: path.resolve("./public/locales"),
|
||||
reloadOnPrerender: process.env.NODE_ENV === "development",
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"italian": "Italian",
|
||||
"language": "Language",
|
||||
"links": "Links",
|
||||
"portugueseBr": "Portuguese (Brazil)",
|
||||
"poweredBy": "Powered by",
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"spanish": "Spanish",
|
||||
|
|
128
public/locales/pt-BR/app.json
Normal file
128
public/locales/pt-BR/app.json
Normal file
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
"12h": "12-horas",
|
||||
"24h": "24-horas",
|
||||
"addParticipant": "Adicionar participante",
|
||||
"addTimeOption": "Adicionar opção de horário",
|
||||
"alreadyVoted": "Você já votou",
|
||||
"applyToAllDates": "Aplicar a todas as datas",
|
||||
"areYouSure": "Você tem certeza?",
|
||||
"back": "Voltar",
|
||||
"calendarHelp": "Você não pode criar uma enquete sem quaisquer opções. Adicione pelo menos uma opção para continuar.",
|
||||
"calendarHelpTitle": "Esqueceu algo?",
|
||||
"cancel": "Cancelar",
|
||||
"comment": "Comentar",
|
||||
"commentPlaceholder": "Deixe um comentário nesta enquete (visível para todos)",
|
||||
"comments": "Comentários",
|
||||
"continue": "Continuar",
|
||||
"copied": "Copiado",
|
||||
"copyLink": "Copiar link",
|
||||
"createdBy": "por <b>{{name}}</b>",
|
||||
"createPoll": "Criar enquete",
|
||||
"creatingDemo": "Criando enquete de demonstração…",
|
||||
"delete": "Excluir",
|
||||
"deleteComment": "Apagar comentário",
|
||||
"deleteDate": "Excluir data",
|
||||
"deletedPoll": "Enquete excluída",
|
||||
"deletedPollInfo": "Esta enquete não existe mais.",
|
||||
"deletePoll": "Excluir enquete",
|
||||
"deletePollDescription": "Todos os dados relacionados a esta enquete serão excluídos. Para confirmar, digite <s>“{{confirmText}}”</s> no espaço abaixo:",
|
||||
"deletingOptionsWarning": "Você está excluindo opções que outros participantes já votaram. Esses votos serão excluídos também.",
|
||||
"demoPollNotice": "Enquetes de demonstração são excluídas automaticamente após 1 dia",
|
||||
"description": "Descrição",
|
||||
"descriptionPlaceholder": "Olá a todos! Por gentileza, escolha as datas que sirva para você!",
|
||||
"donate": "Doe",
|
||||
"editDetails": "Editar detalhes",
|
||||
"editOptions": "Editar opções",
|
||||
"email": "E-mail",
|
||||
"emailPlaceholder": "fulano@email.com.br",
|
||||
"endingGuestSessionNotice": "Uma vez que uma sessão de convidado termine, ela não poderá ser retomada. Você não poderá editar nenhum voto ou comentário que tenha feito nesta sessão.",
|
||||
"endSession": "Encerrar sessão",
|
||||
"errorCreate": "Ops! Houve um problema ao criar sua enquete. O erro foi registrado e tentaremos corrigi-lo.",
|
||||
"exportToCsv": "Exportar para CSV",
|
||||
"finish": "Concluir",
|
||||
"forgetMe": "Esqueça-me",
|
||||
"goToAdmin": "Ir para Admin",
|
||||
"guest": "Convidado",
|
||||
"guestSessionNotice": "Você está usando uma sessão de convidado. Isso nos permite reconhecê-lo caso você voltar mais tarde e poder editar seus votos.",
|
||||
"guestSessionReadMore": "Leia mais sobre sessões de convidado.",
|
||||
"hide": "Ocultar",
|
||||
"ifNeedBe": "Se for necessário",
|
||||
"linkHasExpired": "Seu link expirou ou não é mais válido",
|
||||
"loading": "Carregando…",
|
||||
"loadingParticipants": "Carregando participantes…",
|
||||
"location": "Local",
|
||||
"locationPlaceholder": "Loja de Café do Júlio",
|
||||
"lockPoll": "Bloquear enquete",
|
||||
"login": "Logar",
|
||||
"loginCheckInbox": "Por gentileza, verifique sua caixa de entrada.",
|
||||
"loginMagicLinkSent": "Um link mágico foi enviado para:",
|
||||
"loginSendMagicLink": "Envie-me um link mágico",
|
||||
"loginViaMagicLink": "Login via link mágico",
|
||||
"loginViaMagicLinkDescription": "Enviaremos um e-mail com um link mágico que você possa usar para logar.",
|
||||
"loginWithValidEmail": "Por favor, insira um endereço de e-mail válido",
|
||||
"logout": "Deslogar",
|
||||
"manage": "Gerenciar",
|
||||
"menu": "Menu",
|
||||
"mixedOptionsDescription": "Você não pode ter ambas as opções de data e hora na mesma enquete. Qual você gostaria de manter?",
|
||||
"mixedOptionsKeepDates": "Manter opções de data",
|
||||
"mixedOptionsKeepTimes": "Manter opções de hora",
|
||||
"mixedOptionsTitle": "Aguarde um minuto…🤔",
|
||||
"monday": "Segunda-feira",
|
||||
"monthView": "Visão mensal",
|
||||
"name": "Nome",
|
||||
"namePlaceholder": "Fulano de Tal",
|
||||
"newPoll": "Nova enquete",
|
||||
"next": "Avançar",
|
||||
"nextMonth": "Próximo mês",
|
||||
"no": "Não",
|
||||
"noDatesSelected": "Nenhuma data selecionada",
|
||||
"notificationsDisabled": "As notificações foram desabilitadas",
|
||||
"notificationsOff": "Notificações desativadas",
|
||||
"notificationsOn": "Notificações ativadas",
|
||||
"notificationsOnDescription": "Um e-mail será enviado para <b>{{email}}</b> quando houver atividade nesta enquete.",
|
||||
"notificationsVerifyEmail": "Você precisa confirmar seu e-mail para ativar as notificações",
|
||||
"ok": "Ok",
|
||||
"options": "Opções",
|
||||
"participant": "Participante",
|
||||
"participantCount_other": "{{count}} participantes",
|
||||
"participantCount": "{{count}} participante",
|
||||
"pollHasBeenLocked": "Esta enquete foi bloqueada",
|
||||
"pollHasBeenVerified": "Sua enquete foi verificada",
|
||||
"pollOwnerNotice": "Oi {{name}}, parece que você é o proprietário desta enquete.",
|
||||
"pollsEmpty": "Nenhuma enquete criada",
|
||||
"possibleAnswers": "Possíveis respostas",
|
||||
"preferences": "Preferências",
|
||||
"previousMonth": "Mês anterior",
|
||||
"profileLogin": "Perfil - Login",
|
||||
"profileUser": "Perfil - {{username}}",
|
||||
"requiredNameError": "Nome é obrigatório",
|
||||
"save": "Salvar",
|
||||
"saveInstruction": "Selecione sua disponibilidade e clique <b>{{save}}</b>",
|
||||
"share": "Compartilhar",
|
||||
"shareDescription": "Dê este link para os seus <b>participantes</b> para permitir que eles votem na sua enquete.",
|
||||
"shareLink": "Compartilhar via link",
|
||||
"specifyTimes": "Especificar horários",
|
||||
"specifyTimesDescription": "Incluir os horários de início e fim para cada opção",
|
||||
"stepSummary": "Passo {{current}} de {{total}}",
|
||||
"sunday": "Domingo",
|
||||
"timeAndDate": "Hora & data",
|
||||
"timeFormat": "Formato de hora:",
|
||||
"timeZone": "Fuso horário:",
|
||||
"title": "Título",
|
||||
"titlePlaceholder": "Reunião mensal",
|
||||
"today": "Hoje",
|
||||
"unlockPoll": "Desbloquear enquete",
|
||||
"unverifiedMessage": "Um e-mail foi enviado para <b>{{email}}</b> com um link para verificar o endereço de e-mail.",
|
||||
"user": "Usuário",
|
||||
"vote": "Votar",
|
||||
"voteCount_other": "{{count}} votos",
|
||||
"voteCount": "{{count}} voto",
|
||||
"weekStartsOn": "A semana começa em",
|
||||
"weekView": "Visão semanal",
|
||||
"whatsThis": "O que é isso?",
|
||||
"yes": "Sim",
|
||||
"you": "Você",
|
||||
"yourDetails": "Seus detalhes",
|
||||
"yourName": "Seu nome…",
|
||||
"yourPolls": "Suas enquetes"
|
||||
}
|
21
public/locales/pt-BR/common.json
Normal file
21
public/locales/pt-BR/common.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"blog": "Blog",
|
||||
"discussions": "Discussões",
|
||||
"donate": "Doe",
|
||||
"english": "English",
|
||||
"footerCredit": "Feito por <a>@imlukevella</a>",
|
||||
"footerSponsor": "Este projeto é financiado pelo usuário. Por gentileza, considere apoiá-lo fazendo uma <a>doação</a>.",
|
||||
"french": "Français",
|
||||
"german": "Deutsch",
|
||||
"home": "Início",
|
||||
"italian": "L'italiano",
|
||||
"language": "Idioma",
|
||||
"links": "Links",
|
||||
"poweredBy": "Desenvolvido por",
|
||||
"privacyPolicy": "Política de Privacidade",
|
||||
"spanish": "Español",
|
||||
"starOnGithub": "Qualifique-nos no GitHub",
|
||||
"support": "Suporte",
|
||||
"swedish": "Svenska",
|
||||
"volunteerTranslator": "Ajude a traduzir esta página"
|
||||
}
|
6
public/locales/pt-BR/errors.json
Normal file
6
public/locales/pt-BR/errors.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"notFoundTitle": "404 Página não encontrada",
|
||||
"notFoundDescription": "Não conseguimos encontrar a página que você está procurando.",
|
||||
"goToHome": "Ir para o início",
|
||||
"startChat": "Iniciar chat"
|
||||
}
|
36
public/locales/pt-BR/homepage.json
Normal file
36
public/locales/pt-BR/homepage.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"3Ls": "Sim—com 3 <e>L</e>s",
|
||||
"adFree": "Sem anúncios",
|
||||
"adFreeDescription": "Você pode dar um descanso ao seu bloqueador de anúncios — Você não vai precisar dele aqui.",
|
||||
"comments": "Comentários",
|
||||
"commentsDescription": "Participantes podem comentar na sua enquete e os comentários ficarão visíveis para todos.",
|
||||
"features": "Funcionalidades",
|
||||
"featuresSubheading": "Agendamento, da maneira inteligente",
|
||||
"follow": "Seguir",
|
||||
"getStarted": "Comece agora",
|
||||
"heroSubText": "Encontre o dia certo sem contratempos",
|
||||
"heroText": "Agende<br/><s>reuniões</s><br />com facilidade",
|
||||
"links": "Links",
|
||||
"liveDemo": "Demonstração ao vivo",
|
||||
"metaDescription": "Crie enquetes e vote para encontrar o melhor dia ou hora. Uma alternativa gratuita ao Doodle.",
|
||||
"metaTitle": "Rallly - Agende reuniões de grupo",
|
||||
"mobileFriendly": "Compatível com dispositivos móveis",
|
||||
"mobileFriendlyDescription": "Funciona muito bem em dispositivos móveis para que os participantes possam responder às enquetes onde estiverem.",
|
||||
"new": "Novo",
|
||||
"noLoginRequired": "Não requer login",
|
||||
"noLoginRequiredDescription": "Você não precisa fazer login para criar ou participar de uma enquete",
|
||||
"notifications": "Notificações",
|
||||
"notificationsDescription": "Saiba quem respondeu. Seja notificado quando os participantes votarem ou comentarem na sua enquete.",
|
||||
"openSource": "Código aberto",
|
||||
"openSourceDescription": "O projeto é totalmente de código aberto e <a>disponível no GitHub</a>.",
|
||||
"participant": "Participante",
|
||||
"participantCount_other": "{{count}} participantes",
|
||||
"participantCount": "{{count}} participante",
|
||||
"perfect": "Perfeito!",
|
||||
"principles": "Princípios",
|
||||
"principlesSubheading": "Não somos como os outros",
|
||||
"selfHostable": "Auto-hospedável",
|
||||
"selfHostableDescription": "Execute em seu próprio servidor para ter controle total dos seus dados",
|
||||
"timeSlots": "Intervalos de tempo",
|
||||
"timeSlotsDescription": "Defina os horários de início e fim individuais para cada opção em sua enquete. Os horários podem ser automaticamente ajustados ao fuso horário de cada participante ou podem ser definidos para ignorar completamente o fuso horário."
|
||||
}
|
|
@ -20,8 +20,9 @@ export const LanguageSelect: React.VoidFunctionComponent<{
|
|||
>
|
||||
<option value="en">{t("english")}</option>
|
||||
<option value="es">{t("spanish")}</option>
|
||||
<option value="fr">{t("french")}</option>
|
||||
<option value="de">{t("german")}</option>
|
||||
<option value="pt-BR">{t("portugueseBr")}</option>
|
||||
<option value="fr">{t("french")}</option>
|
||||
<option value="sv">{t("swedish")}</option>
|
||||
</select>
|
||||
);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
const supportedLocales = ["en", "es", "de", "fr", "sv"];
|
||||
const supportedLocales = ["en", "es", "de", "fr", "pt-BR", "sv"];
|
||||
|
||||
export function middleware({ headers, cookies, nextUrl }: NextRequest) {
|
||||
const locale =
|
||||
const language =
|
||||
cookies.get("NEXT_LOCALE") ??
|
||||
(headers
|
||||
.get("accept-language")
|
||||
|
@ -14,8 +14,11 @@ export function middleware({ headers, cookies, nextUrl }: NextRequest) {
|
|||
|
||||
const newUrl = nextUrl.clone();
|
||||
|
||||
if (supportedLocales.includes(locale)) {
|
||||
newUrl.pathname = `/${locale}${newUrl.pathname}`;
|
||||
if (supportedLocales.includes(language)) {
|
||||
newUrl.pathname = `/${language}${newUrl.pathname}`;
|
||||
} else if (language === "pt") {
|
||||
// For now we send all portuguese language requests to pt-BR
|
||||
newUrl.pathname = `/pt-BR${newUrl.pathname}`;
|
||||
}
|
||||
|
||||
return NextResponse.rewrite(newUrl);
|
||||
|
|
|
@ -50,6 +50,11 @@ const dayjsLocales: Record<
|
|||
timeFormat: "24h",
|
||||
import: () => import("dayjs/locale/sv"),
|
||||
},
|
||||
"pt-BR": {
|
||||
weekStartsOn: "sunday",
|
||||
timeFormat: "24h",
|
||||
import: () => import("dayjs/locale/pt-br"),
|
||||
},
|
||||
};
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
@ -84,17 +89,17 @@ export const DayjsProvider: React.VoidFunctionComponent<{
|
|||
|
||||
// Using language instead of router.locale because when transitioning from homepage to
|
||||
// the app via <Link locale={false}> it will be set to "en" instead of the current locale.
|
||||
const locale = i18n.language;
|
||||
const localeConfig = dayjsLocales[i18n.language];
|
||||
|
||||
const [weekStartsOn = dayjsLocales[locale].weekStartsOn, , setWeekStartsOn] =
|
||||
const [weekStartsOn = localeConfig.weekStartsOn, , setWeekStartsOn] =
|
||||
useLocalStorage<StartOfWeek>("rallly-week-starts-on");
|
||||
|
||||
const [timeFormat = dayjsLocales[locale].timeFormat, setTimeFormat] =
|
||||
const [timeFormat = localeConfig.timeFormat, setTimeFormat] =
|
||||
useLocalStorage<TimeFormat>("rallly-time-format");
|
||||
|
||||
const { value: dayjsLocale } = useAsync(async () => {
|
||||
return await dayjsLocales[locale ?? "en"].import();
|
||||
}, [locale]);
|
||||
return await localeConfig.import();
|
||||
}, [localeConfig]);
|
||||
|
||||
if (!dayjsLocale) {
|
||||
// wait for locale to load before rendering content
|
||||
|
@ -103,19 +108,26 @@ export const DayjsProvider: React.VoidFunctionComponent<{
|
|||
|
||||
dayjs.locale({
|
||||
...dayjsLocale,
|
||||
weekStart: weekStartsOn ? (weekStartsOn === "monday" ? 1 : 0) : undefined,
|
||||
formats: {
|
||||
weekStart: weekStartsOn
|
||||
? weekStartsOn === "monday"
|
||||
? 1
|
||||
: 0
|
||||
: dayjsLocale.weekStart,
|
||||
formats:
|
||||
localeConfig.timeFormat !== timeFormat
|
||||
? {
|
||||
...dayjsLocale.formats,
|
||||
LT: timeFormat === "12h" ? "h:mm A" : "H:mm",
|
||||
},
|
||||
}
|
||||
: dayjsLocale.formats,
|
||||
});
|
||||
|
||||
return (
|
||||
<DayjsContext.Provider
|
||||
value={{
|
||||
dayjs,
|
||||
weekStartsOn: weekStartsOn ?? dayjsLocales[locale].weekStartsOn,
|
||||
timeFormat: timeFormat ?? dayjsLocales[locale].timeFormat,
|
||||
weekStartsOn: weekStartsOn ?? localeConfig.weekStartsOn,
|
||||
timeFormat: timeFormat ?? localeConfig.timeFormat,
|
||||
setWeekStartsOn,
|
||||
setTimeFormat,
|
||||
}}
|
||||
|
|
Loading…
Add table
Reference in a new issue