Support locales

This commit is contained in:
Manav Rathi 2024-02-23 18:49:23 +05:30
parent 3e9538f59e
commit 760552f650
4 changed files with 46 additions and 38 deletions

View file

@ -2,8 +2,8 @@ name: Sync crowdin translation
on:
push:
paths: # run action automatically when en/translation.json file is changed
- "apps/photos/public/locales/en/translation.json"
paths: # run action automatically when en-US/translation.json file is changed
- "apps/photos/public/locales/en-US/translation.json"
branches: [main]
schedule:
- cron: "0 */24 * * *" # Every 24 hours - https://crontab.guru/#0_*/12_*_*_*

View file

@ -17,15 +17,15 @@ import { getUserLocaleString } from '@ente/shared/storage/localStorage/helpers';
*/
export const localeName = (locale: SupportedLocale) => {
switch (locale) {
case 'en':
case 'en-US':
return 'English';
case 'fr':
case 'fr-FR':
return 'Français';
case 'zh':
case 'zh-CH':
return '中文';
case 'nl':
case 'nl-NL':
return 'Nederlands';
case 'es':
case 'es-ES':
return 'Español';
}
};

View file

@ -3,4 +3,4 @@ api_token_env: CROWDIN_PERSONAL_TOKEN
files:
- source: /apps/photos/public/locales/en/translation.json
translation: /apps/photos/public/locales/%two_letters_code%/translation.json
translation: /apps/photos/public/locales/%locale%/translation.json

View file

@ -17,8 +17,15 @@ import { includes } from "@/utils/type-guards";
* languages than this. When a translation reaches a high enough coverage, say
* 90%, then we manually add it to this list of supported languages.
*/
export const supportedLocales = ["en", "fr", "zh", "nl", "es"] as const;
/** The type of {@link supportedLocale}s. */
export const supportedLocales = [
"en-US",
"fr-FR",
"zh-CH",
"nl-NL",
"es-ES",
] as const;
/** The type of {@link supportedLocale}s. */
export type SupportedLocale = (typeof supportedLocales)[number];
/**
@ -49,10 +56,24 @@ export const setupI18n = async (savedLocaleString?: string) => {
// Option docs: https://www.i18next.com/overview/configuration-options
.init({
debug: isDevBuild,
returnEmptyString: false,
fallbackLng: "en",
// i18next calls it language, but it really is the locale
lng: locale,
// Tell i18next about the locales we support
supportedLngs: supportedLocales,
// Ask it to fetch only exact matches
//
// By default, if the lng was set to, say, en-GB, i18n would make
// network requests for ["en-GB", "en", "dev"] (where dev is the
// default fallback). By setting `load` to "currentOnly", we ask
// i18next to only try and fetch "en-GB" (i.e. the exact match).
load: "currentOnly",
// Disallow empty strings as valid translations.
//
// This way, empty strings will fallback to `fallbackLng`
returnEmptyString: false,
// The language to use if translation for a particular key in the
// current `lng` is not available.
fallbackLng: "en-US",
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
@ -68,7 +89,6 @@ export const setupI18n = async (savedLocaleString?: string) => {
"br",
],
},
load: "languageOnly",
});
i18n.services.formatter?.add("dateTime", (value, lng) => {
@ -80,18 +100,6 @@ export const setupI18n = async (savedLocaleString?: string) => {
});
};
/**
* Return the current locale in which our user interface is being shown.
*
* Note that this may be different from the user's locale. For example, the
* browser might be set to en-GB, but since we don't support that specific
* variant of English, this value will be (say) en-US.
*/
export const currentLocale = () => {
const locale = i18n.resolvedLanguage;
return locale && includes(supportedLocales, locale) ? locale : "en";
};
/**
* Return the closest / best matching {@link SupportedLocale}.
*
@ -109,20 +117,20 @@ export function closestSupportedLocale(
const ss = savedLocaleString;
if (ss && includes(supportedLocales, ss)) return ss;
/*
// An older version of our code had stored only the language code, not the
// full locale. Map these to the default region we'd started off with.
switch (savedLocaleString) {
case "en":
return Language.en;
return "en-US";
case "fr":
return Language.fr;
return "fr-FR";
case "zh":
return Language.zh;
return "zh-CH";
case "nl":
return Language.nl;
return "nl-NL";
case "es":
return Language.es;
return "es-ES";
}
*/
for (const us of getUserLocales()) {
// Exact match
@ -130,18 +138,18 @@ export function closestSupportedLocale(
// Language match
if (us.startsWith("en")) {
return "en";
return "en-US";
} else if (us.startsWith("fr")) {
return "fr";
return "fr-FR";
} else if (us.startsWith("zh")) {
return "zh";
return "zh-CH";
} else if (us.startsWith("nl")) {
return "nl";
return "nl-NL";
} else if (us.startsWith("es")) {
return "es";
return "es-ES";
}
}
// Fallback
return "en";
return "en-US";
}