diff --git a/src/app/config.ts b/src/app/config.ts index 7f52ab4c..483cac97 100644 --- a/src/app/config.ts +++ b/src/app/config.ts @@ -21,11 +21,11 @@ export const TEMPLATE_DESCRIPTION = 'Store photos with original camera data'; export const TEMPLATE_REPO_OWNER = 'sambecker'; export const TEMPLATE_REPO_NAME = 'exif-photo-blog'; export const TEMPLATE_REPO_BRANCH = 'main'; -// eslint-disable-next-line max-len -export const TEMPLATE_REPO_URL = `https://github.com/${TEMPLATE_REPO_OWNER}/${TEMPLATE_REPO_NAME}`; +export const TEMPLATE_REPO_URL = + `https://github.com/${TEMPLATE_REPO_OWNER}/${TEMPLATE_REPO_NAME}`; export const TEMPLATE_REPO_URL_FORK = `${TEMPLATE_REPO_URL}/fork`; -// eslint-disable-next-line max-len -export const TEMPLATE_REPO_URL_README = `${TEMPLATE_REPO_URL}?tab=readme-ov-file`; +export const TEMPLATE_REPO_URL_README = + `${TEMPLATE_REPO_URL}?tab=readme-ov-file`; export const VERCEL_GIT_PROVIDER = process.env.NEXT_PUBLIC_VERCEL_GIT_PROVIDER; diff --git a/src/cmdk/CommandKClient.tsx b/src/cmdk/CommandKClient.tsx index 20b45801..a040071f 100644 --- a/src/cmdk/CommandKClient.tsx +++ b/src/cmdk/CommandKClient.tsx @@ -631,7 +631,7 @@ export default function CommandKClient({ key={heading} heading={
diff --git a/src/components/ImageInput.tsx b/src/components/ImageInput.tsx index 9b25ee3f..a16b6963 100644 --- a/src/components/ImageInput.tsx +++ b/src/components/ImageInput.tsx @@ -85,7 +85,7 @@ export default function ImageInput({ > {isUploading ? filesLength > 1 - ? APP_TEXT.utility.paginate( + ? APP_TEXT.utility.paginateAction( fileUploadIndex + 1, filesLength, APP_TEXT.admin.uploading, diff --git a/src/i18n/index.ts b/src/i18n/index.ts index ac4d4881..7ef7979b 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -1,6 +1,7 @@ import US_EN from './locales/us-en'; import PT_BR from './locales/pt-br'; import PT_PT from './locales/pt-pt'; +import { enUS, ptBR, pt } from 'date-fns/locale'; export type I18N = typeof US_EN; @@ -8,6 +9,60 @@ export type I18NDeepPartial = { [key in keyof I18N]?: Partial; } +const getDateFnLocale = (locale: string) => { + switch (locale) { + case 'pt-pt': return pt; + case 'pt-br': return ptBR; + default: return enUS; + } +}; + +const generateI18NWithFunctions = (i18nText: I18N) => { + return { + ...i18nText, + category: { + ...i18nText.category, + cameraTitle: (camera: string) => + i18nText.category.cameraTitle.replace('{{camera}}', camera), + cameraShare: (camera: string) => + i18nText.category.cameraShare.replace('{{camera}}', camera), + taggedPhrase: (tag: string) => + i18nText.category.taggedPhrase.replace('{{tag}}', tag), + recipeShare: (recipe: string) => + i18nText.category.recipeShare.replace('{{recipe}}', recipe), + filmShare: (film: string) => + i18nText.category.filmShare.replace('{{film}}', film), + focalLengthTitle: (focal: string) => + i18nText.category.focalLengthTitle.replace('{{focal}}', focal), + focalLengthShare: (focal: string) => + i18nText.category.focalLengthShare.replace('{{focal}}', focal), + }, + admin: { + ...i18nText.admin, + deleteConfirm: (photoTitle: string) => + i18nText.admin.deleteConfirm.replace('{{photoTitle}}', photoTitle), + }, + misc: { + ...i18nText.misc, + copyPhrase: (label: string) => + i18nText.misc.copyPhrase.replace('{{label}}', label), + }, + utility: { + ...i18nText.utility, + paginate: (index: number, count: number) => + i18nText.utility.paginate + .replace('{{index}}', index.toString()) + .replace('{{count}}', count.toString()), + paginateAction: (index: number, count: number, action: string) => + i18nText.utility.paginateAction + .replace('{{index}}', index.toString()) + .replace('{{count}}', count.toString()) + .replace('{{action}}', action), + }, + dateLocale: getDateFnLocale(i18nText.locale), + }; +}; + export const LOCALE_TEXT: Record = { 'pt-br': PT_BR, 'pt-pt': PT_PT, @@ -15,17 +70,17 @@ export const LOCALE_TEXT: Record = { export const getTextForLocale = ( locale = '', -): I18N => { +) => { const text = US_EN; Object.entries(LOCALE_TEXT[locale.toLocaleLowerCase()] ?? {}) .forEach(([key, value]) => { // Fall back to English for missing keys text[key as keyof I18N] = { - ...text[key as keyof I18N], - ...value, - } as any; + ...text[key as keyof I18N] as any, + ...value as any, + }; }); - return text; + return generateI18NWithFunctions(text); }; diff --git a/src/i18n/locales/pt-br.ts b/src/i18n/locales/pt-br.ts index ab33517e..6573ad1e 100644 --- a/src/i18n/locales/pt-br.ts +++ b/src/i18n/locales/pt-br.ts @@ -1,7 +1,7 @@ import { I18NDeepPartial } from '..'; -import { ptBR } from 'date-fns/locale'; const TEXT: I18NDeepPartial = { + locale: 'pt-br', photo: { photo: 'Foto', photoPlural: 'Fotos', @@ -13,25 +13,25 @@ const TEXT: I18NDeepPartial = { category: { camera: 'Câmera', cameraPlural: 'Câmeras', - cameraTitle: (camera: string) => `Tirado com ${camera}`, - cameraShare: (camera: string) => `Fotos tiradas com ${camera}`, + cameraTitle: 'Tirado com {{camera}}', + cameraShare: 'Fotos tiradas com {{camera}}', lens: 'Lente', lensPlural: 'Lentes', tag: 'Tag', tagPlural: 'Tags', taggedPhotos: 'Fotos marcadas', - taggedPhrase: (tag: string) => `Fotos marcadas com '${tag}'`, + taggedPhrase: 'Fotos marcadas com {{tag}}', taggedFavs: 'Fotos favoritas', recipe: 'Receita', recipePlural: 'Receitas', - recipeShare: (recipe: string) => `Fotos da receita ${recipe}`, + recipeShare: 'Fotos da receita {{recipe}}', film: 'Filme', filmPlural: 'Filmes', - filmShare: (film: string) => `Fotos tiradas com ${film}`, + filmShare: 'Fotos tiradas com {{film}}', focalLength: 'Distância focal', focalLengthPlural: 'Distâncias focais', - focalLengthTitle: (focal: string) => `Distância focal ${focal}`, - focalLengthShare: (focal: string) => `Fotos tiradas em ${focal}`, + focalLengthTitle: 'Distância focal {{focal}}', + focalLengthShare: 'Fotos tiradas em {{focal}}', }, nav: { home: 'Início', @@ -93,8 +93,7 @@ const TEXT: I18NDeepPartial = { download: 'Baixar', sync: 'Sincronizar', delete: 'Excluir', - deleteConfirm: (photoTitle: string) => - `Tem certeza de que deseja excluir "${photoTitle}"?`, + deleteConfirm: 'Tem certeza de que deseja excluir "{{photoTitle}}"?', }, onboarding: { setupComplete: 'Configuração concluída!', @@ -109,18 +108,12 @@ const TEXT: I18NDeepPartial = { finishing: 'Finalizando ...', uploading: 'Enviando', repo: 'Feito com', - copyPhrase: (label: string) => `${label} copiado`, + copyPhrase: '{{label}} copiado', }, utility: { - paginate: ( - index: number, - count: number, - action?: string, - ) => action - ? `${action} ${index} de ${count}` - : `${index} de ${count}`, + paginate: '{{index}} de {{count}}', + paginateAction: '{{action}} {{index}} de {{count}}', }, - dateLocale: ptBR, }; export default TEXT; diff --git a/src/i18n/locales/pt-pt.ts b/src/i18n/locales/pt-pt.ts index 39278750..334db3d9 100644 --- a/src/i18n/locales/pt-pt.ts +++ b/src/i18n/locales/pt-pt.ts @@ -1,7 +1,7 @@ import { I18NDeepPartial } from '..'; -import { pt } from 'date-fns/locale'; const TEXT: I18NDeepPartial = { + locale: 'pt-pt', photo: { photo: 'Fotografia', photoPlural: 'Fotografias', @@ -13,25 +13,25 @@ const TEXT: I18NDeepPartial = { category: { camera: 'Máquina Fotográfica', cameraPlural: 'Máquinas Fotográficas', - cameraTitle: (camera: string) => `Tirado com ${camera}`, - cameraShare: (camera: string) => `Fotografias tiradas com ${camera}`, + cameraTitle: 'Tirado com {{camera}}', + cameraShare: 'Fotografias tiradas com {{camera}}', lens: 'Objetiva', lensPlural: 'Objetivas', tag: 'Etiqueta', tagPlural: 'Etiquetas', taggedPhotos: 'Fotografias etiquetadas', - taggedPhrase: (tag: string) => `Fotos etiquetadas com '${tag}'`, + taggedPhrase: 'Fotos etiquetadas com {{tag}}', taggedFavs: 'Fotografias favoritas', recipe: 'Receita', recipePlural: 'Receitas', - recipeShare: (recipe: string) => `Fotografias da receita ${recipe}`, + recipeShare: 'Fotografias da receita {{recipe}}', film: 'Filme fotográfico', filmPlural: 'Filmes fotográficos', - filmShare: (film: string) => `Fotografias tiradas com ${film}`, + filmShare: 'Fotografias tiradas com {{film}}', focalLength: 'Distância focal', focalLengthPlural: 'Distâncias focais', - focalLengthTitle: (focal: string) => `Distância focal ${focal}`, - focalLengthShare: (focal: string) => `Fotos tiradas em ${focal}`, + focalLengthTitle: 'Distância focal {{focal}}', + focalLengthShare: 'Fotos tiradas em {{focal}}', }, nav: { home: 'Início', @@ -93,8 +93,7 @@ const TEXT: I18NDeepPartial = { download: 'Descarregar', sync: 'Sincronizar', delete: 'Excluir', - deleteConfirm: (photoTitle: string) => - `Tens certeza de que deseja excluir "${photoTitle}"?`, + deleteConfirm: 'Tens certeza de que deseja excluir "{{photoTitle}}"?', }, onboarding: { setupComplete: 'Configuração concluída!', @@ -109,18 +108,12 @@ const TEXT: I18NDeepPartial = { finishing: 'A finalizar ...', uploading: 'A enviar', repo: 'Feito com', - copyPhrase: (label: string) => `${label} copiado`, + copyPhrase: '{{label}} copiado', }, utility: { - paginate: ( - index: number, - count: number, - action?: string, - ) => action - ? `${action} ${index} de ${count}` - : `${index} de ${count}`, + paginate: '{{index}} de {{count}}', + paginateAction: '{{action}} {{index}} de {{count}}', }, - dateLocale: pt, }; export default TEXT; diff --git a/src/i18n/locales/us-en.ts b/src/i18n/locales/us-en.ts index ee373834..6d1490d9 100644 --- a/src/i18n/locales/us-en.ts +++ b/src/i18n/locales/us-en.ts @@ -1,6 +1,5 @@ -import { enUS } from 'date-fns/locale'; - const TEXT = { + locale: 'en-us', photo: { photo: 'Photo', photoPlural: 'Photos', @@ -12,25 +11,25 @@ const TEXT = { category: { camera: 'Camera', cameraPlural: 'Cameras', - cameraTitle: (camera: string) => `Shot on ${camera}`, - cameraShare: (camera: string) => `Photos shot on ${camera}`, + cameraTitle: 'Shot on {{camera}}', + cameraShare: 'Photos shot on {{camera}}', lens: 'Lens', lensPlural: 'Lenses', tag: 'Tag', tagPlural: 'Tags', taggedPhotos: 'Tagged Photos', - taggedPhrase: (tag: string) => `Photos tagged '${tag}'`, + taggedPhrase: 'Photos tagged {{tag}}', taggedFavs: 'Favorite Photos', recipe: 'Recipe', recipePlural: 'Recipes', - recipeShare: (recipe: string) => `${recipe} recipe photos`, + recipeShare: '{{recipe}} recipe photos', film: 'Film', filmPlural: 'Films', - filmShare: (film: string) => `Photos shot on ${film}`, + filmShare: 'Photos shot on {{film}}', focalLength: 'Focal Length', focalLengthPlural: 'Focal Lengths', - focalLengthTitle: (focal: string) => `Focal Length ${focal}`, - focalLengthShare: (focal: string) => `Photos shot at ${focal}`, + focalLengthTitle: 'Focal Length {{focal}}', + focalLengthShare: 'Photos shot at {{focal}}', }, nav: { home: 'Home', @@ -92,8 +91,7 @@ const TEXT = { download: 'Download', sync: 'Sync', delete: 'Delete', - deleteConfirm: (photoTitle: string) => - `Are you sure you want to delete "${photoTitle}?"`, + deleteConfirm: 'Are you sure you want to delete "{{photoTitle}}?"', }, onboarding: { setupComplete: 'Setup Complete!', @@ -108,18 +106,12 @@ const TEXT = { finishing: 'Finishing ...', uploading: 'Uploading', repo: 'Made with', - copyPhrase: (label: string) => `${label} copied`, + copyPhrase: '{{label}} copied', }, utility: { - paginate: ( - index: number, - count: number, - action?: string, - ) => action - ? `${action} ${index} of ${count}` - : `${index} of ${count}`, + paginate: '{{index}} of {{count}}', + paginateAction: '{{action}} {{index}} of {{count}}', }, - dateLocale: enUS, }; export default TEXT; diff --git a/src/photo/PhotoHeader.tsx b/src/photo/PhotoHeader.tsx index 9f639099..7eec0d93 100644 --- a/src/photo/PhotoHeader.tsx +++ b/src/photo/PhotoHeader.tsx @@ -155,13 +155,13 @@ export default function PhotoHeader({ }} />} : - {APP_TEXT.utility.paginate( + {APP_TEXT.utility.paginateAction( paginationIndex, paginationCount, entityVerb)}