diff --git a/.github/workflows/push-localization.yml b/.github/workflows/push-localization.yml new file mode 100644 index 0000000..d068aa9 --- /dev/null +++ b/.github/workflows/push-localization.yml @@ -0,0 +1,34 @@ +name: Push a new commit with inline translations on cms files + +on: + push: + pull_request: + branches-ignore: + - main + +jobs: + commit-inline-translations: + runs-on: ubuntu-latest + + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: "20.x" + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Add inline translations + run: yarn inline-translations + + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Add inline translations" diff --git a/.github/workflows/validate-cms.yml b/.github/workflows/validate-cms.yml index b00a53d..b370820 100644 --- a/.github/workflows/validate-cms.yml +++ b/.github/workflows/validate-cms.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v2 diff --git a/.gitignore b/.gitignore index b512c09..4af056d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +project.inlang/.cache \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..84ad162 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +### FE Content + +This repository serves as a Content Management System (CMS) for the [Osmosis Frontend](https://github.com/osmosis-labs/osmosis-frontend). + +#### Translation + +The content in this repository is available in various languages, with translations automatically handled by inlang. Follow these steps to translate content: + +1. Add an English translation in the CMS file under the localization property by inserting an "en" key. + Example: + ```json + "localization": { + "en": {} + } + ``` +2. After committing and pushing changes to a branch, the CI process will automatically add the translations to the same branch. +3. To manually handle translations, execute the command `yarn inline-translations`. diff --git a/tests/validate-cms.spec.js b/__tests__/validate-cms.spec.js similarity index 100% rename from tests/validate-cms.spec.js rename to __tests__/validate-cms.spec.js diff --git a/cms/swap-rotating-banner.json b/cms/swap-rotating-banner.json index 74517ca..0643b6e 100644 --- a/cms/swap-rotating-banner.json +++ b/cms/swap-rotating-banner.json @@ -3,59 +3,229 @@ "banners": [ { "name": "milkTIA", - "start_date": "2023-12-18T14:30:00.123Z", - "end_date": "2024-01-25T14:30:00.123Z", - "header": "Got Milk?", - "subheader": "$milkTIA now available on Osmosis", - "external_url": "/pool/1335", - "icon_image_url": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/milkTIA.svg", - "icon_image_alt": "milkTIA logo", + "startDate": "2023-12-18T14:30:00.123Z", + "endDate": "2024-01-25T14:30:00.123Z", + "headerOrTranslationKey": "milkHeader", + "subheaderOrTranslationKey": "milkSubheader", + "externalUrl": "/pool/1335", + "iconImageUrl": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/milkTIA.svg", + "iconImageAltOrTranslationKey": "milkImageAlt", "gradient": "linear-gradient(93.62deg, #F7D1F2 -6.6%, #4B99FC 46.78%, #D3AAFB 105.39%)", - "font_color": "#213469", - "arrow_color": "#213469", + "fontColor": "#213469", + "arrowColor": "#213469", "featured": true }, { "name": "Place limit orders", - "start_date": "2023-06-22T14:30:00.123Z", - "end_date": "2024-06-22T14:30:00.123Z", - "header": "Place limit orders", - "subheader": "Experience pro trading with TFM", - "external_url": "https://osmosis.tfm.com/", - "icon_image_url": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/place-limit-order.svg", - "icon_image_alt": "Variable chart decreasing to the lower right, then increasing to the upper right with dollar signs", + "startDate": "2023-06-22T14:30:00.123Z", + "endDate": "2024-06-22T14:30:00.123Z", + "headerOrTranslationKey": "tfmHeader", + "subheaderOrTranslationKey": "tfmSubheader", + "externalUrl": "https://osmosis.tfm.com/", + "iconImageUrl": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/place-limit-order.svg", + "iconImageAltOrTranslationKey": "Variable chart decreasing to the lower right, then increasing to the upper right with dollar signs", "gradient": "linear-gradient(136deg, #3B154F 0%, #10061C 47.66%, #0E2654 100%)", - "font_color": "#E4E1FB", - "arrow_color": "#BAF3FF", + "fontColor": "#E4E1FB", + "arrowColor": "#BAF3FF", "featured": true }, { "name": "Looking to DCA?", - "start_date": "2023-06-22T14:30:00.123Z", - "end_date": "2024-06-22T14:30:00.123Z", - "header": "Looking to DCA?", - "subheader": "Set up recurring swaps with CalcFi", - "external_url": "https://app.calculated.fi/create-strategy/dca-in/assets/?chain=Osmosis&utm_source=osmosis_dex", - "icon_image_url": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/dollar-cost-averaging.svg", - "icon_image_alt": "Chart increasing to the upper right with dollar signs", + "startDate": "2023-06-22T14:30:00.123Z", + "endDate": "2024-06-22T14:30:00.123Z", + "headerOrTranslationKey": "calcFiHeader", + "subheaderOrTranslationKey": "calcFiSubheader", + "externalUrl": "https://app.calculated.fi/create-strategy/dca-in/assets/?chain=Osmosis&utm_source=osmosis_dex", + "iconImageUrl": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/dollar-cost-averaging.svg", + "iconImageAltOrTranslationKey": "Chart increasing to the upper right with dollar signs", "gradient": "linear-gradient(136deg, #543E17 0%, #161A24 47.66%, #183B5B 100%)", - "font_color": "#FFF5C7", - "arrow_color": "#EED75F", + "fontColor": "#FFF5C7", + "arrowColor": "#EED75F", "featured": true }, { "name": "Margined Protocol", - "start_date": "2023-11-10T14:30:00.123Z", - "end_date": "2024-11-10T14:30:00.123Z", - "header": "Feeling bullish?", - "subheader": "Try quadratic leverage on Margined", - "external_url": "https://trade.margined.io/", - "icon_image_url": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/feeling-bullish.svg", - "icon_image_alt": "Chart increasing exponentially to the upper right over a background of dots", + "startDate": "2023-11-10T14:30:00.123Z", + "endDate": "2024-11-10T14:30:00.123Z", + "headerOrTranslationKey": "marginedHeader", + "subheaderOrTranslationKey": "marginedSubheader", + "externalUrl": "https://trade.margined.io/", + "iconImageUrl": "https://raw.githubusercontent.com/osmosis-labs/fe-content/main/images/feeling-bullish.svg", + "iconImageAltOrTranslationKey": "Chart increasing exponentially to the upper right over a background of dots", "gradient": "linear-gradient(136deg, #020200 0%, #000000 47.66%, #373E24 100%)", - "font_color": "#CBFD50", - "arrow_color": "#CBFD50", + "fontColor": "#CBFD50", + "arrowColor": "#CBFD50", "featured": true } - ] + ], + "localization": { + "en": { + "milkHeader": "Got Milk?", + "milkSubheader": "$milkTIA now available on Osmosis", + "milkImageAlt": "milkTIA logo", + "tfmHeader": "Place limit orders", + "tfmSubheader": "Experience pro trading with TFM", + "tfmImageAlt": "Variable chart decreasing to the lower right, then increasing to the upper right with dollar signs", + "calcFiHeader": "Looking to DCA?", + "calcFiSubheader": "Set up recurring swaps with CalcFi", + "calcFiImageAlt": "Chart increasing to the upper right with dollar signs", + "marginedHeader": "Feeling bullish?", + "marginedSubheader": "Try quadratic leverage on Margined", + "marginedImageAlt": "Chart increasing exponentially to the upper right over a background of dots" + }, + "es": { + "milkHeader": "¿Tienes leche?", + "milkSubheader": "$milkTIA ya disponible en Osmosis", + "milkImageAlt": "logotipo de la leche TIA", + "tfmHeader": "Realizar órdenes limitadas", + "tfmSubheader": "Experimente el comercio profesional con TFM", + "tfmImageAlt": "Gráfico de variables que disminuye hacia la parte inferior derecha y luego aumenta hacia la parte superior derecha con signos de dólar", + "calcFiHeader": "¿Buscando al DCA?", + "calcFiSubheader": "Configure swaps recurrentes con CalcFi", + "calcFiImageAlt": "Gráfico que aumenta hacia la parte superior derecha con signos de dólar", + "marginedHeader": "¿Te sientes optimista?", + "marginedSubheader": "Pruebe el apalancamiento cuadrático en Margined", + "marginedImageAlt": "Gráfico que aumenta exponencialmente hacia la esquina superior derecha sobre un fondo de puntos" + }, + "fa": { + "milkHeader": "شیر دارید؟", + "milkSubheader": "$milkTIA اکنون در Osmosis موجود است", + "milkImageAlt": "آرم milkTIA", + "tfmHeader": "ثبت سفارشات محدود", + "tfmSubheader": "تجارت حرفه ای را با TFM تجربه کنید", + "tfmImageAlt": "نمودار متغیر به سمت راست پایین کاهش می یابد، سپس با علائم دلار به سمت راست بالا افزایش می یابد", + "calcFiHeader": "به دنبال DCA هستید؟", + "calcFiSubheader": "تبادلات مکرر را با CalcFi تنظیم کنید", + "calcFiImageAlt": "نمودار به سمت راست بالا با علائم دلار در حال افزایش است", + "marginedHeader": "احساس صعود؟", + "marginedSubheader": "اهرم درجه دوم را روی Margined امتحان کنید", + "marginedImageAlt": "نمودار به صورت تصاعدی به سمت راست بالا در پس زمینه ای از نقاط افزایش می یابد" + }, + "fr": { + "milkHeader": "Avoir du lait?", + "milkSubheader": "$milkTIA maintenant disponible sur Osmosis", + "milkImageAlt": "logo laitTIA", + "tfmHeader": "Passer des ordres limités", + "tfmSubheader": "Faites l'expérience du trading professionnel avec TFM", + "tfmImageAlt": "Graphique variable décroissant vers le bas à droite, puis augmentant vers le haut à droite avec des signes dollar", + "calcFiHeader": "Vous envisagez le DCA ?", + "calcFiSubheader": "Mettre en place des swaps récurrents avec CalcFi", + "calcFiImageAlt": "Graphique croissant vers le coin supérieur droit avec des signes dollar", + "marginedHeader": "Vous vous sentez optimiste ?", + "marginedSubheader": "Essayez l'effet de levier quadratique sur Margined", + "marginedImageAlt": "Graphique augmentant de façon exponentielle vers le coin supérieur droit sur un fond de points" + }, + "ko": { + "milkHeader": "우유를 얻었다?", + "milkSubheader": "이제 Osmosis에서 $milkTIA를 이용할 수 있습니다.", + "milkImageAlt": "우유TIA 로고", + "tfmHeader": "지정가 주문하기", + "tfmSubheader": "TFM으로 프로 트레이딩을 경험해보세요", + "tfmImageAlt": "오른쪽 아래로 감소한 후 달러 기호와 함께 오른쪽 위로 증가하는 가변 차트", + "calcFiHeader": "DCA를 찾고 계십니까?", + "calcFiSubheader": "CalcFi로 반복 스왑 설정", + "calcFiImageAlt": "달러 기호가 있는 오른쪽 상단으로 증가하는 차트", + "marginedHeader": "낙관적인 느낌?", + "marginedSubheader": "Margined에서 2차 레버리지를 사용해 보세요.", + "marginedImageAlt": "점 배경 위에 오른쪽 상단으로 기하급수적으로 증가하는 차트" + }, + "pl": { + "milkHeader": "Masz mleko?", + "milkSubheader": "$milkTIA jest teraz dostępny na Osmosis", + "milkImageAlt": "logo milkTIA", + "tfmHeader": "Składaj zamówienia z limitem", + "tfmSubheader": "Doświadcz profesjonalnego handlu z TFM", + "tfmImageAlt": "Zmienny wykres malejący w prawym dolnym rogu, a następnie rosnący w prawym górnym rogu ze znakami dolara", + "calcFiHeader": "Szukasz DCA?", + "calcFiSubheader": "Konfiguruj cykliczne wymiany za pomocą CalcFi", + "calcFiImageAlt": "Wykres rosnący w prawym górnym rogu ze znakami dolara", + "marginedHeader": "Czujesz się uparty?", + "marginedSubheader": "Wypróbuj dźwignię kwadratową na Margined", + "marginedImageAlt": "Wykres rosnący wykładniczo w prawym górnym rogu na tle kropek" + }, + "pt-br": { + "milkHeader": "Tenho leite?", + "milkSubheader": "$milkTIA agora disponível em Osmose", + "milkImageAlt": "logotipo do leiteTIA", + "tfmHeader": "Faça pedidos com limite", + "tfmSubheader": "Experimente negociação profissional com TFM", + "tfmImageAlt": "Gráfico variável diminuindo para o canto inferior direito e aumentando para o canto superior direito com cifrões", + "calcFiHeader": "Olhando para o DCA?", + "calcFiSubheader": "Configure swaps recorrentes com CalcFi", + "calcFiImageAlt": "Gráfico aumentando para o canto superior direito com cifrões", + "marginedHeader": "Sentindo-se otimista?", + "marginedSubheader": "Experimente a alavancagem quadrática em Margined", + "marginedImageAlt": "Gráfico aumentando exponencialmente no canto superior direito sobre um fundo de pontos" + }, + "ro": { + "milkHeader": "Am lapte?", + "milkSubheader": "$milkTIA acum disponibil pe Osmosis", + "milkImageAlt": "sigla milkTIA", + "tfmHeader": "Plasați comenzi limită", + "tfmSubheader": "Experiență de tranzacționare profesională cu TFM", + "tfmImageAlt": "Graficul variabil scade în dreapta jos, apoi crește în dreapta sus cu semnele dolarului", + "calcFiHeader": "Cauți DCA?", + "calcFiSubheader": "Configurați schimburi recurente cu CalcFi", + "calcFiImageAlt": "Grafic în creștere în dreapta sus cu semnele dolarului", + "marginedHeader": "Te simți optimist?", + "marginedSubheader": "Încercați pârghia pătratică pe Margined", + "marginedImageAlt": "Graficul crește exponențial în dreapta sus pe un fundal de puncte" + }, + "tr": { + "milkHeader": "Süt var mı?", + "milkSubheader": "$milkTIA artık Osmosis'te mevcut", + "milkImageAlt": "sütTIA logosu", + "tfmHeader": "Limit emirleri ver", + "tfmSubheader": "TFM ile profesyonel ticareti deneyimleyin", + "tfmImageAlt": "Dolar işaretleri ile sağ alta doğru azalan, ardından sağ üst tarafa doğru artan değişken grafik", + "calcFiHeader": "DCA'yı mı arıyorsunuz?", + "calcFiSubheader": "CalcFi ile yinelenen takaslar ayarlayın", + "calcFiImageAlt": "Dolar işaretleri ile sağ üste doğru artan grafik", + "marginedHeader": "Yükseliş mi hissediyorsunuz?", + "marginedSubheader": "Margined'de ikinci dereceden kaldıracı deneyin", + "marginedImageAlt": "Noktalardan oluşan bir arka plan üzerinde sağ üste doğru katlanarak artan grafik" + }, + "zh-cn": { + "milkHeader": "有牛奶吗?", + "milkSubheader": "$milkTIA 现已在 Osmosis 上发售", + "milkImageAlt": "牛奶TIA标志", + "tfmHeader": "下限价单", + "tfmSubheader": "通过 TFM 体验专业交易", + "tfmImageAlt": "变量图表向右下方递减,然后以美元符号向右上方递增", + "calcFiHeader": "正在寻找 DCA?", + "calcFiSubheader": "使用 CalcFi 设置定期交换", + "calcFiImageAlt": "图表向右上方增加并带有美元符号", + "marginedHeader": "感觉看涨吗?", + "marginedSubheader": "尝试在保证金上使用二次杠杆", + "marginedImageAlt": "图表在点背景上呈指数增长到右上角" + }, + "zh-hk": { + "milkHeader": "有牛奶嗎?", + "milkSubheader": "$milkTIA 現已在 Osmosis 上架", + "milkImageAlt": "牛奶TIA標誌", + "tfmHeader": "下限價單", + "tfmSubheader": "透過 TFM 體驗專業交易", + "tfmImageAlt": "變數圖表向右下方遞減,然後以美元符號向右上方遞增", + "calcFiHeader": "正在尋找 DCA?", + "calcFiSubheader": "使用 CalcFi 設定定期交換", + "calcFiImageAlt": "圖表向右上方增加並帶有美元符號", + "marginedHeader": "感覺看漲嗎?", + "marginedSubheader": "試試在保證金上使用二次槓桿", + "marginedImageAlt": "圖表在點背景上呈指數增長到右上角" + }, + "zh-tw": { + "milkHeader": "有牛奶嗎?", + "milkSubheader": "$milkTIA 現已在 Osmosis 上架", + "milkImageAlt": "牛奶TIA標誌", + "tfmHeader": "下限價單", + "tfmSubheader": "透過 TFM 體驗專業交易", + "tfmImageAlt": "變數圖表向右下方遞減,然後以美元符號向右上方遞增", + "calcFiHeader": "正在尋找 DCA?", + "calcFiSubheader": "使用 CalcFi 設定定期交換", + "calcFiImageAlt": "圖表向右上方增加並帶有美元符號", + "marginedHeader": "感覺看漲嗎?", + "marginedSubheader": "試試在保證金上使用二次槓桿", + "marginedImageAlt": "圖表在點背景上呈指數增長到右上角" + } + } } diff --git a/cms/top-announcement-banner.json b/cms/top-announcement-banner.json index ba1f114..a8f22d2 100644 --- a/cms/top-announcement-banner.json +++ b/cms/top-announcement-banner.json @@ -1,5 +1,53 @@ { "$schema": "../schemas/top-announcement-banner.schema.json", "isChainHalted": false, - "banner": null + "banner": { + "enTextOrLocalizationPath": "title", + "link": { + "enTextOrLocalizationKey": "linkLearnMore", + "isExternal": true, + "url": "https://www.google.com" + }, + "localStorageKey": "top-announcement-banner-test", + "startDate": "2024-01-08T00:00:00.000Z", + "endDate": "2024-02-01T00:00:00.000Z" + }, + "localization": { + "en": { "title": "Testing!", "linkLearnMore": "Click here to learn more." }, + "es": { + "title": "¡Pruebas!", + "linkLearnMore": "Clic aquí para saber más." + }, + "fa": { + "title": "آزمایش کردن!", + "linkLearnMore": "برای اطلاعات بیشتر اینجا کلیک کنید." + }, + "fr": { + "title": "Essai!", + "linkLearnMore": "Cliquez ici pour en savoir plus." + }, + "ko": { + "title": "테스트!", + "linkLearnMore": "자세한 내용을 보려면 여기를 클릭하세요." + }, + "pl": { + "title": "Testowanie!", + "linkLearnMore": "Kliknij tutaj, aby dowiedzieć się więcej." + }, + "pt-br": { + "title": "Testando!", + "linkLearnMore": "Clique aqui para saber mais." + }, + "ro": { + "title": "Testare!", + "linkLearnMore": "Apasa aici pentru a afla mai multe." + }, + "tr": { + "title": "Test yapmak!", + "linkLearnMore": "Daha fazlasını öğrenmek için buraya tıklayın." + }, + "zh-cn": { "title": "测试!", "linkLearnMore": "点击这里了解更多。" }, + "zh-hk": { "title": "測試!", "linkLearnMore": "點這裡了解更多。" }, + "zh-tw": { "title": "測試!", "linkLearnMore": "點這裡了解更多。" } + } } diff --git a/package.json b/package.json index cad26fa..6df8cf8 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,19 @@ "description": "", "main": "index.js", "scripts": { - "test": "vitest" + "test": "vitest", + "inline-translations": "tsx ./scripts/translate-cms.js" }, "keywords": [], "author": "", "license": "Apache-2.0", "devDependencies": { + "@inlang/cli": "^2.0.0", "ajv": "^8.12.0", "ajv-cli": "^5.0.0", "ajv-formats": "^2.1.1", + "prettier": "^3.1.1", + "tsx": "^4.7.0", "vitest": "^1.1.3" } } diff --git a/project.inlang/settings.json b/project.inlang/settings.json new file mode 100644 index 0000000..824c972 --- /dev/null +++ b/project.inlang/settings.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "sourceLanguageTag": "en", + "languageTags": [ + "en", + "es", + "fa", + "fr", + "ko", + "pl", + "pt-br", + "ro", + "tr", + "zh-cn", + "zh-hk", + "zh-tw" + ], + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/plugin-json@4/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@1/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@1/dist/index.js" + ], + "plugin.inlang.json": { + "pathPattern": "./project.inlang/.cache/{languageTag}.json" + } +} diff --git a/schemas/swap-rotating-banner.schema.json b/schemas/swap-rotating-banner.schema.json index 543e49b..9cd6537 100644 --- a/schemas/swap-rotating-banner.schema.json +++ b/schemas/swap-rotating-banner.schema.json @@ -10,37 +10,37 @@ "name": { "type": "string" }, - "start_date": { + "startDate": { "type": "string", "format": "date-time" }, - "end_date": { + "endDate": { "type": "string", "format": "date-time" }, - "header": { + "headerOrTranslationKey": { "type": "string" }, - "subheader": { + "subheaderOrTranslationKey": { "type": "string" }, - "external_url": { + "externalUrl": { "type": "string" }, - "icon_image_url": { + "iconImageUrl": { "type": "string", "format": "uri" }, - "icon_image_alt": { + "iconImageAltOrTranslationKey": { "type": "string" }, "gradient": { "type": "string" }, - "font_color": { + "fontColor": { "type": "string" }, - "arrow_color": { + "arrowColor": { "type": "string" }, "featured": { @@ -49,16 +49,16 @@ }, "required": [ "name", - "start_date", - "end_date", - "header", - "subheader", - "external_url", - "icon_image_url", - "icon_image_alt", + "startDate", + "endDate", + "headerOrTranslationKey", + "subheaderOrTranslationKey", + "externalUrl", + "iconImageUrl", + "iconImageAltOrTranslationKey", "gradient", - "font_color", - "arrow_color", + "fontColor", + "arrowColor", "featured" ] } diff --git a/scripts/translate-cms.js b/scripts/translate-cms.js index 1406544..ab04db7 100644 --- a/scripts/translate-cms.js +++ b/scripts/translate-cms.js @@ -1,77 +1,132 @@ -const fs = require("fs"); -const path = require("path"); +import fs from "fs"; +import path from "path"; +import prettier from "prettier"; +import { spawn } from "child_process"; -// Load the settings -const settings = JSON.parse( - fs.readFileSync("project.inlang/settings.json", "utf8") -); +const cmsDirectoryPath = "./cms"; +const cacheLocationDirectory = "./project.inlang/.cache"; +const cmsFiles = fs.readdirSync(cmsDirectoryPath); + +if (!fs.existsSync(cacheLocationDirectory)) { + fs.mkdirSync(cacheLocationDirectory, { recursive: true }); +} -// Load the banner file -const obj = JSON.parse( - fs.readFileSync("cms/top-announcement-banner.json", "utf8") +const inlangSettings = JSON.parse( + fs.readFileSync("project.inlang/settings.json", "utf8") ); -/** - * Set a value in an object using a path. - * - * @example - * // Set the value of `object.a.b.c` to `3` - * setObjValue(object, "a.b.c", 3); - */ -function setObjValue(object, path, value) { - const clone = { ...object }; - const way = path.replace(/\[/g, ".").replace(/\]/g, "").split("."), - last = way.pop(); - - way.reduce(function (o, k, i, kk) { - return (o[k] = - o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {})); - }, object)[last] = value; - return clone; +async function writeFile(filePath, content) { + const formatted = await prettier.format(JSON.stringify(content), { + parser: "json", + }); + fs.writeFileSync(path.resolve(cmsDirectoryPath, filePath), formatted, { + encoding: "utf8", + }); } -/** - * Get a value in an object using a path. - * @example - * // Get the value of `object.a.b.c` - * getObjValue("a.b.c", object); - */ -function getObjValue(key, object) { - return key.split(".").reduce((o, i) => o[i], object); +function spawnPromise(...command) { + return new Promise((resolve, reject) => { + const child = spawn(...command); + + // use child.stdout.setEncoding('utf8'); if you want text chunks + child.stdout.on("data", (chunk) => { + console.log(chunk.toString()); + }); + + // since these are streams, you can pipe them elsewhere + child.stderr.on("data", (chunk) => { + console.log("Error: ", chunk.toString()); + }); + + child.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`child process exited with code ${code}`)); + } + }); + }); } -// Iterate over each language -settings.languageTags.forEach((languageTag) => { - // Load the localization file for this language - const localization = JSON.parse( - fs.readFileSync(path.join("localizations", `${languageTag}.json`), "utf8") - ); - - let resultObj = { ...obj }; - Object.entries(resultObj).forEach(([key, value]) => { - // Set the value in the banner object - resultObj = setObjValue( - obj, - `${key}.enTextOrLocalizationPath`, - languageTag +async function main() { + // Create language files + for (const languageTag of inlangSettings.languageTags) { + const languageFilePath = path.resolve( + cacheLocationDirectory, + `${languageTag}.json` ); - // Inline the translations - obj[key][`enTextOrLocalizationPath`] = - localization[obj[key].enTextOrLocalizationPath]; - }); + if (!fs.existsSync(languageFilePath)) { + writeFile(languageFilePath, {}, { encoding: "utf8" }); + } - setObjValue(banner, `banner.enTextOrLocalizationPath`, languageTag); - // Inline the translations - banner.banner[`enTextOrLocalizationPath`] = - localization[banner.banner.enTextOrLocalizationPath]; - banner.banner.link[`enTextOrLocalizationKey`] = - localization[banner.banner.link.enTextOrLocalizationKey]; -}); - -// Save the updated banner file -fs.writeFileSync( - "cms/top-announcement-banner.json", - JSON.stringify(banner, null, 2), - "utf8" -); + const languageContent = {}; + for (const filePath of cmsFiles) { + const namespace = filePath.split(".")[0]; + const fileContent = JSON.parse( + fs.readFileSync(path.resolve(cmsDirectoryPath, filePath), "utf8") + ); + + if (!fileContent.localization) { + continue; + } + + languageContent[namespace] = + fileContent?.localization?.[languageTag] ?? {}; + } + + // Create en.json file with all namespaces + await writeFile( + path.resolve(cacheLocationDirectory, `${languageTag}.json`), + languageContent + ); + } + + await spawnPromise("inlang", [ + "machine", + "translate", + "-f", + "--project", + "./project.inlang", + ]); + + for (const filePath of cmsFiles) { + const namespace = filePath.split(".")[0]; + + const content = JSON.parse( + fs.readFileSync(path.resolve(cmsDirectoryPath, filePath), "utf8") + ); + + if (!content.localization) { + continue; + } + + // Create localization file for each language tag + inlangSettings.languageTags.forEach((languageTag) => {}); + + content.localization = inlangSettings.languageTags.reduce( + (acc, languageTag) => { + const localizationFile = JSON.parse( + fs.readFileSync( + path.join(cacheLocationDirectory, `${languageTag}.json`), + "utf8" + ) + ); + + const namespaceContent = localizationFile[namespace]; + + if (!namespaceContent) { + return acc; + } + + acc[languageTag] = namespaceContent; + return acc; + }, + {} + ); + + await writeFile(path.resolve(cmsDirectoryPath, filePath), content); + } +} + +main(); diff --git a/yarn.lock b/yarn.lock index 68ef436..51481c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -117,6 +117,14 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== +"@inlang/cli@^2.0.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@inlang/cli/-/cli-2.4.0.tgz#271e9201083e938a9563610e9416c3170c87e261" + integrity sha512-7Ev0x0w/S+PJlHyLC2RPRQNHppaU9ZxGKqtCm8jFplXqFxrlL7uU3z5+cyRM6u1jthd3smx1D0PlYcCJW9tU1Q== + dependencies: + esbuild-wasm "^0.19.2" + fs-extra "11.1.1" + "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -376,7 +384,12 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== -esbuild@^0.19.3: +esbuild-wasm@^0.19.2: + version "0.19.11" + resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.19.11.tgz#4ed96cdd1a289bc08432a25fd38b7331d3eac98d" + integrity sha512-MIhnpc1TxERUHomteO/ZZHp+kUawGEc03D/8vMHGzffLvbFLeDe6mwxqEZwlqBNY7SLWbyp6bBQAcCen8+wpjQ== + +esbuild@^0.19.3, esbuild@~0.19.10: version "0.19.11" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96" integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA== @@ -449,6 +462,15 @@ fast-json-patch@^2.0.0: dependencies: fast-deep-equal "^2.0.1" +fs-extra@11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -469,6 +491,13 @@ get-stream@^8.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== +get-tsconfig@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce" + integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A== + dependencies: + resolve-pkg-maps "^1.0.0" + glob@^7.1.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -481,6 +510,11 @@ glob@^7.1.0: once "^1.3.0" path-is-absolute "^1.0.0" +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + human-signals@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" @@ -539,6 +573,15 @@ jsonc-parser@^3.2.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + local-pkg@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" @@ -679,6 +722,11 @@ postcss@^8.4.32: picocolors "^1.0.0" source-map-js "^1.0.2" +prettier@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== + pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -703,6 +751,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + rollup@^4.2.0: version "4.9.3" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.3.tgz#12f54775f359409641b5a71a86fe226a7c1d6b67" @@ -794,6 +847,16 @@ tinyspy@^2.2.0: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.0.tgz#9dc04b072746520b432f77ea2c2d17933de5d6ce" integrity sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg== +tsx@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.0.tgz#1689cfe7dda495ca1f9a66d4cad79cb57b9f6f4a" + integrity sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg== + dependencies: + esbuild "~0.19.10" + get-tsconfig "^4.7.2" + optionalDependencies: + fsevents "~2.3.3" + type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -804,6 +867,11 @@ ufo@^1.3.0: resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"