Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4687b23
Add portuguese (brazil)
gewfy Jun 20, 2025
240ec02
Add pt-BR to translations
gewfy Jun 20, 2025
504e9b6
pt-BR email receivers
gewfy Jun 20, 2025
67ebe1b
Rename pt language tag to pt-PT
gewfy Jun 20, 2025
63cc22f
Interpret "pt" as "pt-PT"
gewfy Jun 22, 2025
53d35e0
Correct portuguese fallbacks
gewfy Jun 22, 2025
b44585b
Namespaced content might be undefined
gewfy Jun 22, 2025
71d3883
Show confirm in chosen language
gewfy Jun 22, 2025
73d7cb8
Fix tests
gewfy Jun 22, 2025
3c10711
Add Brazilian Portuguese translations for various UI components
gewfy Jun 26, 2025
37d0ca5
Add Brazilian Portuguese translations and update collections and exer…
gewfy Jun 26, 2025
b352d3d
Add Brazilian Portuguese translations and update descriptions, names,…
gewfy Jun 26, 2025
16af0aa
Add Brazilian Portuguese translations for various tags and update the…
gewfy Jun 26, 2025
51717f0
Add Brazilian Portuguese translations for email footer and user report
gewfy Jun 26, 2025
2e1cae9
Add support for overriding published flag for exercises during CSV im…
gewfy Jun 26, 2025
d86c3d9
Add Brazilian Portuguese translations and update content for multiple…
gewfy Jun 26, 2025
967e76b
Update language resolver to use 'pt-PT' for Portuguese instead of 'pt'
gewfy Jun 26, 2025
9bf9eac
Refactor posts API to destructure language from context and remove it…
gewfy Jun 26, 2025
6988d06
Add migration script to update language from 'pt' to 'pt-PT' in Fires…
gewfy Jun 26, 2025
2e2d53a
Update minimum app and bundle versions to 2.60.0 in killswitch API
gewfy Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/lib/components/Cards/Cards.library.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const CardsList = () => (
<Spacer16 />
<Card
title="Accepting thoughts and feelings"
language="pt"
language="pt-PT"
tags={DUMMY_TAGS}
hostProfile={DUMMY_HOST}
cardStyle={DUMMY_TRANSPARENT_LOTTIE_CARD_STYLE}
Expand Down Expand Up @@ -134,7 +134,7 @@ const CardsList = () => (
<Spacer16 />
<Card
title="Accepting thoughts and feeeeeeeeeeeeeelings"
language="pt"
language="pt-PT"
tags={DUMMY_TAGS}
hostProfile={DUMMY_HOST}
cardStyle={DUMMY_IMAGE_CARD_STYLE}
Expand Down
6 changes: 3 additions & 3 deletions client/src/lib/i18n/hooks/useLanguageFromRoute.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ describe('useLanguageFromRoute', () => {

it('supports a comma separated list of languages', () => {
mockGetCurrentRoute.mockReturnValueOnce({
params: {language: 'pt,sv'},
params: {language: 'pt-PT,sv'},
});

renderHook(() => useLanguageFromRoute());

expect(mockFindBestLanguageTag).toHaveBeenCalledTimes(1);
expect(mockFindBestLanguageTag).toHaveBeenCalledWith(['pt', 'sv']);
expect(mockFindBestLanguageTag).toHaveBeenCalledWith(['pt-PT', 'sv']);

expect(useAppState.getState().settings.preferredLanguage).toEqual('pt');
expect(useAppState.getState().settings.preferredLanguage).toEqual('pt-PT');
});

it('does nothing if language param is not set', () => {
Expand Down
24 changes: 19 additions & 5 deletions client/src/lib/i18n/hooks/useReloadResourceBundles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,47 @@ describe('useReloadResourceBundles', () => {
await result.current();
});

expect(i18n.removeResourceBundle).toHaveBeenCalledTimes(32);
expect(i18n.removeResourceBundle).toHaveBeenCalledTimes(36);
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('en', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith(
'pt-PT',
'categories',
);
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('sv', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('ja', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('da', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('cs', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('nl', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('es', 'categories');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('en', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith(
'pt-PT',
'collections',
);
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('sv', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('ja', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('da', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('cs', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('nl', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('es', 'collections');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('en', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt-PT', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt-BR', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('sv', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('ja', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('da', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('cs', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('nl', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('es', 'tags');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('en', 'exercises');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('pt', 'exercises');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith(
'pt-PT',
'exercises',
);
expect(i18n.removeResourceBundle).toHaveBeenCalledWith(
'pt-BR',
'exercises',
);
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('sv', 'exercises');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('ja', 'exercises');
expect(i18n.removeResourceBundle).toHaveBeenCalledWith('da', 'exercises');
Expand Down
8 changes: 4 additions & 4 deletions client/src/lib/i18n/hooks/useSetPreferedLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ const useSetPreferredLanguage = () => {
} else {
const language = LANGUAGES[languageTag];
Alert.alert(
t('unsupportedLanguage.title'),
t('unsupportedLanguage.message', {language}),
t('unsupportedLanguage.title', {lng: languageTag}),
t('unsupportedLanguage.message', {language, lng: languageTag}),
[
{
text: t('unsupportedLanguage.dismiss'),
text: t('unsupportedLanguage.dismiss', {lng: languageTag}),
onPress: () => {},
style: 'cancel',
},
{
text: t('unsupportedLanguage.confirm'),
text: t('unsupportedLanguage.confirm', {lng: languageTag}),
onPress: () => setSettings({preferredLanguage: languageTag}),
},
],
Expand Down
6 changes: 5 additions & 1 deletion client/src/lib/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export const init = (language?: LANGUAGE_TAG) =>
lng: language || findBestLanguageTag(CLIENT_LANGUAGE_TAGS)?.languageTag,
supportedLngs: LANGUAGE_TAGS,
preload: LANGUAGE_TAGS,
fallbackLng: DEFAULT_LANGUAGE_TAG,
fallbackLng: {
pt: ['pt-PT', DEFAULT_LANGUAGE_TAG], // "pt-PT" was previously saved in the appState as "pt"
'pt-BR': [DEFAULT_LANGUAGE_TAG], // "pt-BR" should not fall back to "pt-PT"
default: [DEFAULT_LANGUAGE_TAG],
},
// To trigger the backend middleware to load publishable content they have to be removed first.
// Removing them in buildContent creates somewhat of a mess in backend adding them back.
resources: omitPublishableContent(content.i18n),
Expand Down
2 changes: 1 addition & 1 deletion client/src/lib/i18n/plugins/filterContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const filterContent: BackendModule = {
namespace: I18nNamespace,
callback: ReadCallback,
) {
let namespaceContent = content.i18n[language][namespace];
let namespaceContent = content.i18n?.[language]?.[namespace];

if (PUBLISHABLE_NAMESPACES.includes(namespace)) {
namespaceContent = filterPublishedContent(namespaceContent);
Expand Down
10 changes: 8 additions & 2 deletions client/src/lib/i18n/utils/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import content from '../../../../../content/content.json';
jest.mock('../../../../../content/content.json', () => ({
i18n: {
en: {categories: {}, collections: {}, tags: {}, exercises: {}, keep: true},
pt: {categories: {}, collections: {}, tags: {}, exercises: {}, keep: true},
'pt-PT': {
categories: {},
collections: {},
tags: {},
exercises: {},
keep: true,
},
sv: {categories: {}, collections: {}, tags: {}, exercises: {}, keep: true},
ja: {categories: {}, collections: {}, tags: {}, exercises: {}, keep: true},
da: {categories: {}, collections: {}, tags: {}, exercises: {}, keep: true},
Expand All @@ -23,7 +29,7 @@ describe('i18n - utils', () => {
it('should remove publishable content from content', () => {
expect(omitPublishableContent(content.i18n)).toEqual({
en: {keep: true},
pt: {keep: true},
'pt-PT': {keep: true},
sv: {keep: true},
ja: {keep: true},
da: {keep: true},
Expand Down
3 changes: 2 additions & 1 deletion client/src/lib/i18n/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ export const omitPublishableContent = (resources: typeof content.i18n) => {
string,
Record<string, string>
>; // Can't delete exercises in type content.i18n since it's not optional

LANGUAGE_TAGS.forEach(language => {
PUBLISHABLE_NAMESPACES.forEach(namespace => {
delete allResources[language][namespace];
delete allResources?.[language]?.[namespace];
});
});

Expand Down
14 changes: 8 additions & 6 deletions content/importFromCsv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ if (!CSV_FILE) {
}

const skipLanguageMergeForTypes = ['email', 'ui'];
const overridePublishedFlagForTypes = ['exercises'];

type Translation = {
Type: string;
Expand Down Expand Up @@ -68,13 +69,14 @@ const main = async () => {
[TO_LANGUAGE_TAG]: mergeDeepWith(
mergeWithArrays,
unflatten(fileTranslations),
mergeDeepWith(
mergeWithArrays,
content[TO_LANGUAGE_TAG],
skipLanguageMergeForTypes.includes(type)
mergeDeepWith(mergeWithArrays, content[TO_LANGUAGE_TAG], {
...(skipLanguageMergeForTypes.includes(type)
? {}
: content[FROM_LANGUAGE_TAG],
),
: content[FROM_LANGUAGE_TAG]),
...(overridePublishedFlagForTypes.includes(type)
? {published: false}
: {}),
}),
),
};

Expand Down
31 changes: 30 additions & 1 deletion content/src/categories/07c58365-832b-4b3f-b926-c09682632441.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/deal_with_stress_kodv1x.json"
}
},
"pt": {
"pt-PT": {
"id": "07c58365-832b-4b3f-b926-c09682632441",
"exercises": [
"961656ea-021c-4faa-ae03-46d6ace4be4b",
Expand Down Expand Up @@ -152,5 +152,34 @@
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/deal_with_stress_kodv1x.json"
}
},
"pt-BR": {
"name": "Lidar com o estresse",
"id": "07c58365-832b-4b3f-b926-c09682632441",
"exercises": [
"961656ea-021c-4faa-ae03-46d6ace4be4b",
"f4f8a536-5683-40a3-a139-5e3031687cec",
"3188a5ed-a1d6-451c-ae2a-f44f4df37495",
"2d096e25-3f0b-48da-8557-3db607b98ef8",
"c7911238-ca9f-4499-9cae-63dfcd0c79c5",
"94575e97-fe03-4bfd-94a6-50aaf721d47e",
"b18c1cff-bb43-44b1-81a1-2877cc018ab4",
"1e96f73b-8193-4aa6-a52c-31355eac3c08",
"b7f8731c-64d7-4c0f-9bc8-a3e50ec2eaf7",
"095f9642-73b6-4c9a-ae9a-ea7dea7363f5",
"c5b1197a-4eec-4699-9dad-0e3d6323967b",
"12f448d2-39bc-4232-b8cf-b6cb570c7e00",
"33a188a2-6871-47d6-a754-f5c246bd6b9a"
],
"collections": [
"af1c4ac9-1bae-4cb1-8c98-e1f98a8aea66",
"8cb72f0d-3aad-4fe6-bf08-560b108bb439",
"716c2b31-612c-40c4-8e85-90f0a2af380e",
"1d35e981-4b8e-47f0-887a-0c90d21fb991"
],
"published": true,
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/deal_with_stress_kodv1x.json"
}
}
}
22 changes: 21 additions & 1 deletion content/src/categories/4fba05de-cc63-4613-9c84-a34f4cbbc58e.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/working_on_your.._yedzqe.json"
}
},
"pt": {
"pt-PT": {
"id": "4fba05de-cc63-4613-9c84-a34f4cbbc58e",
"name": "Trabalhar nas relações",
"collections": [
Expand Down Expand Up @@ -107,5 +107,25 @@
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/working_on_your.._yedzqe.json"
}
},
"pt-BR": {
"name": "Trabalhar nos seus relacionamentos",
"id": "4fba05de-cc63-4613-9c84-a34f4cbbc58e",
"collections": [
"716c2b31-612c-40c4-8e85-90f0a2af380e"
],
"exercises": [
"648e1802-eb45-47b0-a42e-dd986669a4eb",
"c5b1197a-4eec-4699-9dad-0e3d6323967b",
"5b69ff57-10c4-4288-afc7-a6f6ed212531",
"095f9642-73b6-4c9a-ae9a-ea7dea7363f5",
"b1e6cc8e-03a4-4f74-8884-2896c391ab07",
"df2c5312-c869-4ab7-8ac1-1875a04e2229",
"c7911238-ca9f-4499-9cae-63dfcd0c79c5"
],
"published": true,
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/working_on_your.._yedzqe.json"
}
}
}
32 changes: 31 additions & 1 deletion content/src/categories/b7257c0a-f180-405f-8aff-05f9f75bddbd.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/understand_myself_qeibfi.json"
}
},
"pt": {
"pt-PT": {
"id": "b7257c0a-f180-405f-8aff-05f9f75bddbd",
"collections": [
"1d35e981-4b8e-47f0-887a-0c90d21fb991",
Expand Down Expand Up @@ -157,5 +157,35 @@
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/understand_myself_qeibfi.json"
}
},
"pt-BR": {
"name": "Entender a si mesmo",
"id": "b7257c0a-f180-405f-8aff-05f9f75bddbd",
"collections": [
"1d35e981-4b8e-47f0-887a-0c90d21fb991",
"dcb02b73-c515-44a1-bee3-850dbd5eb2a1",
"716c2b31-612c-40c4-8e85-90f0a2af380e",
"68172f5c-955a-43e0-9cef-ae3bc77c9593"
],
"exercises": [
"185889ec-753b-4e2c-8322-3004013e8a6e",
"2d096e25-3f0b-48da-8557-3db607b98ef8",
"5b0dea9f-c665-41ce-a779-601d0cfa433d",
"c7911238-ca9f-4499-9cae-63dfcd0c79c5",
"c5b1197a-4eec-4699-9dad-0e3d6323967b",
"61adeaf2-70ab-4c6c-854c-2c16f762a3c5",
"f4f8a536-5683-40a3-a139-5e3031687cec",
"13dfd5b5-f0af-4783-9fe1-3ba7773bcb89",
"19135d2e-0e8d-418c-939d-18b0e62215ff",
"2ea0d73d-4bfe-4e23-9124-2998acc9743f",
"2fdb95f0-d18d-444d-9935-2c71b9b413d4",
"c1c4da35-87af-4e10-a8d9-e6c58571f724",
"c4b1c360-88b8-4e05-915a-407e00aef898",
"e4bf8d17-a774-4702-abfe-c7452c3fee0f"
],
"published": true,
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/understand_myself_qeibfi.json"
}
}
}
27 changes: 26 additions & 1 deletion content/src/categories/e2d46c10-77c3-4784-a9ea-4e7b4939711d.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/find_meaning_wta8nc.json"
}
},
"pt": {
"pt-PT": {
"id": "e2d46c10-77c3-4784-a9ea-4e7b4939711d",
"name": "Encontra significado",
"collections": [
Expand Down Expand Up @@ -132,5 +132,30 @@
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/find_meaning_wta8nc.json"
}
},
"pt-BR": {
"name": "Encontrar sentido",
"id": "e2d46c10-77c3-4784-a9ea-4e7b4939711d",
"collections": [
"d9897547-18a2-4404-b12b-324458021783",
"9739d765-08e4-401c-88e9-3318e75ce41a",
"b77e52b5-c927-4178-ba76-8c3fe3dbf13c"
],
"exercises": [
"fff6f8da-f69c-458f-8905-acee04bd1a1d",
"640e4d9f-bb88-44af-a032-116a82f080f6",
"61adeaf2-70ab-4c6c-854c-2c16f762a3c5",
"0bcb6eb0-fdfe-466d-8603-ae6de15fcbc5",
"5b69ff57-10c4-4288-afc7-a6f6ed212531",
"095f9642-73b6-4c9a-ae9a-ea7dea7363f5",
"12f448d2-39bc-4232-b8cf-b6cb570c7e00",
"2ea0d73d-4bfe-4e23-9124-2998acc9743f",
"648e1802-eb45-47b0-a42e-dd986669a4eb",
"f59b7f66-43b0-4b50-9afe-91092d7dc469"
],
"published": true,
"lottie": {
"source": "https://res.cloudinary.com/cupcake-29k/raw/upload/v1702302654/Lottie/find_meaning_wta8nc.json"
}
}
}
Loading
Loading