Refactor Chinese language codes and i18n file structure

Changed Chinese language codes from 'zh-CN' and 'zh-TW' to 'cn' and 'tw' across backend and frontend. Renamed i18n translation files and updated language switchers and user settings to use new codes. Updated Crowdin configuration for improved hierarchy and project settings.
This commit is contained in:
João Vitória Silva
2025-10-02 10:53:59 +01:00
parent 362cf80ef4
commit eea3240284
142 changed files with 98 additions and 61 deletions

View File

@@ -24,9 +24,9 @@ class Language(Enum):
An enumeration representing supported languages for the application.
Members:
CATALAN: Catalan language code ("ca").
CHINESE_SIMPLIFIED: Simplified Chinese language code ("zh-CN").
CHINESE_TRADITIONAL: Traditional Chinese language code ("zh-TW").
CATALAN: Catalan language code ("ca-ES").
CHINESE_SIMPLIFIED: Simplified Chinese language code ("cn").
CHINESE_TRADITIONAL: Traditional Chinese language code ("tw").
DUTCH: Dutch language code ("nl").
GERMAN: German language code ("de").
FRENCH: French language code ("fr").
@@ -36,8 +36,8 @@ class Language(Enum):
"""
CATALAN = "ca"
CHINESE_SIMPLIFIED = "zh-CN"
CHINESE_TRADITIONAL = "zh-TW"
CHINESE_SIMPLIFIED = "cn"
CHINESE_TRADITIONAL = "tw"
DUTCH = "nl"
GERMAN = "de"
FRENCH = "fr"

View File

@@ -1,37 +1,78 @@
files:
- source: /frontend/app/src/i18n/us/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/%original_file_name%
- source: /frontend/app/src/i18n/us/components/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/%original_file_name%
- source: /frontend/app/src/i18n/us/gears/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/gears/%original_file_name%
- source: /frontend/app/src/i18n/us/strava/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/strava/%original_file_name%
- source: /frontend/app/src/i18n/us/components/activities/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/activities/%original_file_name%
- source: /frontend/app/src/i18n/us/components/activities/modals/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/activities/modals/%original_file_name%
- source: /frontend/app/src/i18n/us/components/followers/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/followers/%original_file_name%
- source: /frontend/app/src/i18n/us/components/gears/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/gears/%original_file_name%
- source: /frontend/app/src/i18n/us/components/health/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/health/%original_file_name%
- source: /frontend/app/src/i18n/us/components/health/healthWeightZone/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/health/healthWeightZone/%original_file_name%
- source: /frontend/app/src/i18n/us/components/navbar/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/navbar/%original_file_name%
- source: /frontend/app/src/i18n/us/components/notifications/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/notifications/%original_file_name%
- source: /frontend/app/src/i18n/us/components/settings/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/settings/%original_file_name%
- source: /frontend/app/src/i18n/us/components/users/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/users/%original_file_name%
- source: /frontend/app/src/i18n/us/components/settings/settingsGeneralZone/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/settings/settingsGeneralZone/%original_file_name%
- source: /frontend/app/src/i18n/us/components/settings/settingsIntegrationsZone/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/settings/settingsIntegrationsZone/%original_file_name%
- source: /frontend/app/src/i18n/us/components/settings/settingsUsersZone/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/settings/settingsUsersZone/%original_file_name%
- source: /frontend/app/src/i18n/us/components/settings/settingsUserSessionsZone/*.json
translation: /frontend/app/src/i18n/%two_letters_code%/components/settings/settingsUserSessionsZone/%original_file_name%
"project_id": "654570"
"preserve_hierarchy": true
"files": [
{
"source": "/frontend/app/src/i18n/us/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/gears/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/gears/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/strava/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/strava/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/activities/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/activities/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/activities/modals/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/activities/modals/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/followers/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/followers/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/gears/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/gears/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/health/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/health/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/health/healthWeightZone/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/health/healthWeightZone/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/navbar/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/navbar/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/notifications/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/notifications/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/settings/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/settings/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/users/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/users/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/settings/settingsGeneralZone/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/settings/settingsGeneralZone/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/settings/settingsIntegrationsZone/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/settings/settingsIntegrationsZone/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/settings/settingsUsersZone/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/settings/settingsUsersZone/%original_file_name%"
},
{
"source": "/frontend/app/src/i18n/us/components/settings/settingsUserSessionsZone/*.json",
"translation": "/frontend/app/src/i18n/%two_letters_code%/components/settings/settingsUserSessionsZone/%original_file_name%"
}
]

View File

@@ -7,9 +7,7 @@
data-bs-toggle="dropdown"
aria-expanded="false"
>
<span :class="'fi fi-cn'" v-if="currentLanguage === 'zh-CN'"></span>
<span :class="'fi fi-tw'" v-else-if="currentLanguage === 'zh-TW'"></span>
<span :class="'fi fi-' + currentLanguage" v-else-if="currentLanguage !== 'ca'"></span>
<span :class="'fi fi-' + currentLanguage" v-if="currentLanguage !== 'ca'"></span>
<span class="fi fi-es-ct" v-else></span>
</a>
@@ -22,9 +20,7 @@
:aria-pressed="currentLanguage === language.value ? 'true' : 'false'"
>
<span class="me-2">{{ language.label }}</span>
<span :class="'fi fi-cn'" v-if="language.value === 'zh-CN'"></span>
<span :class="'fi fi-tw'" v-else-if="language.value === 'zh-TW'"></span>
<span :class="'fi fi-' + language.value" v-else-if="language.value !== 'ca'"></span>
<span :class="'fi fi-' + language.value" v-if="language.value !== 'ca'"></span>
<span class="fi fi-es-ct" v-else></span>
<span v-if="currentLanguage === language.value" class="ms-3"
><font-awesome-icon :icon="['fas', 'check']"
@@ -42,8 +38,8 @@ import { useI18n } from 'vue-i18n'
const { locale, t } = useI18n()
const languages = computed(() => [
{ value: 'ca', label: t('generalItems.languageOption2') },
{ value: 'zh-CN', label: t('generalItems.languageOption8') },
{ value: 'zh-TW', label: t('generalItems.languageOption9') },
{ value: 'cn', label: t('generalItems.languageOption8') },
{ value: 'tw', label: t('generalItems.languageOption9') },
{ value: 'de', label: t('generalItems.languageOption4') },
{ value: 'fr', label: t('generalItems.languageOption5') },
{ value: 'nl', label: t('generalItems.languageOption6') },

View File

@@ -26,8 +26,8 @@ export default {
const { locale, t } = useI18n()
const languages = computed(() => [
{ value: 'ca', label: t('generalItems.languageOption2') },
{ value: 'zh-CN', label: t('generalItems.languageOption8') },
{ value: 'zh-TW', label: t('generalItems.languageOption9') },
{ value: 'cn', label: t('generalItems.languageOption8') },
{ value: 'tw', label: t('generalItems.languageOption9') },
{ value: 'de', label: t('generalItems.languageOption4') },
{ value: 'fr', label: t('generalItems.languageOption5') },
{ value: 'nl', label: t('generalItems.languageOption6') },

View File

@@ -149,10 +149,10 @@
<span v-if="authStore.user.preferred_language == 'ca'">{{
$t('generalItems.languageOption2')
}}</span>
<span v-if="authStore.user.preferred_language == 'zh-CN'">{{
<span v-if="authStore.user.preferred_language == 'cn'">{{
$t('generalItems.languageOption8')
}}</span>
<span v-if="authStore.user.preferred_language == 'zh-TW'">{{
<span v-if="authStore.user.preferred_language == 'tw'">{{
$t('generalItems.languageOption9')
}}</span>
<span v-if="authStore.user.preferred_language == 'de'">{{

View File

@@ -326,8 +326,8 @@
required
>
<option value="ca">{{ $t('generalItems.languageOption2') }}</option>
<option value="zh-CN">{{ $t('generalItems.languageOption8') }}</option>
<option value="zh-TW">{{ $t('generalItems.languageOption9') }}</option>
<option value="cn">{{ $t('generalItems.languageOption8') }}</option>
<option value="tw">{{ $t('generalItems.languageOption9') }}</option>
<option value="de">{{ $t('generalItems.languageOption4') }}</option>
<option value="fr">{{ $t('generalItems.languageOption5') }}</option>
<option value="nl">{{ $t('generalItems.languageOption6') }}</option>

View File

@@ -2,12 +2,12 @@ import { createI18n } from 'vue-i18n'
// Bundle only locale JSON files (root + nested), eagerly so they're in dist
const translationModules = {
...import.meta.glob('./{ca,de,es,fr,nl,pt,us,zh-CN,zh-TW}/*.json', { eager: true }),
...import.meta.glob('./{ca,de,es,fr,nl,pt,us,zh-CN,zh-TW}/**/*.json', { eager: true })
...import.meta.glob('./{ca,de,es,fr,nl,pt,us,cn,tw}/*.json', { eager: true }),
...import.meta.glob('./{ca,de,es,fr,nl,pt,us,cn,tw}/**/*.json', { eager: true })
}
// Define available locales
const locales = ['ca', 'de', 'es', 'fr', 'nl', 'pt', 'us', 'zh-CN', 'zh-TW']
const locales = ['ca', 'de', 'es', 'fr', 'nl', 'pt', 'us', 'cn', 'tw']
// Define all component paths
const componentPaths = {

Some files were not shown because too many files have changed in this diff Show More