diff --git a/.circleci/config.yml b/.circleci/config.yml index 61516b9c9a8a9..1aec593a68ca3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -161,6 +161,9 @@ jobs: - run: name: '`yarn docs:api` changes committed?' command: git diff --exit-code + - run: + name: '`yarn i18n` changes committed?' + command: yarn i18n check-changed test_browser: <<: *defaults docker: diff --git a/package.json b/package.json index 8d387f2897836..2dedd636c9ae1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "storybook:build": "yarn workspace storybook build", "storybook:export": "yarn workspace storybook export", "deduplicate": "node scripts/deduplicate.js", + "i18n": "babel-node -x .ts ./scripts/i18n.ts", "stylelint": "stylelint '**/*.js' '**/*.ts' '**/*.tsx'", "prettier": "node ./scripts/prettier.js --branch next", "prettier:all": "node ./scripts/prettier.js write", @@ -58,6 +59,8 @@ "@babel/plugin-transform-runtime": "^7.16.0", "@babel/register": "^7.16.0", "@babel/runtime": "^7.16.3", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0", "@emotion/cache": "^11.5.0", "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", @@ -71,6 +74,7 @@ "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/plugin-replace": "^3.0.0", "@testing-library/react": "^12.1.2", + "@types/babel__core": "^7.1.16", "@types/chai": "^4.2.22", "@types/chai-dom": "^0.0.11", "@types/enzyme": "^3.10.10", diff --git a/packages/grid/_modules_/grid/locales/arSD.ts b/packages/grid/_modules_/grid/locales/arSD.ts index b854c2fbffdf2..55d7df742d371 100644 --- a/packages/grid/_modules_/grid/locales/arSD.ts +++ b/packages/grid/_modules_/grid/locales/arSD.ts @@ -31,6 +31,7 @@ const arSDGrid: Partial = { toolbarExport: 'تصدير', toolbarExportLabel: 'تصدير', toolbarExportCSV: 'تنزيل كملف CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'ايجاد عمود', diff --git a/packages/grid/_modules_/grid/locales/bgBG.ts b/packages/grid/_modules_/grid/locales/bgBG.ts index f67cef87de29d..55bceae5ae50d 100644 --- a/packages/grid/_modules_/grid/locales/bgBG.ts +++ b/packages/grid/_modules_/grid/locales/bgBG.ts @@ -15,7 +15,7 @@ const bgBGGrid: Partial = { toolbarDensityStandard: 'Стандартна', toolbarDensityComfortable: 'Комфортна', - // GridColumns selector toolbar button text + // Columns selector toolbar button text toolbarColumns: 'Колони', toolbarColumnsLabel: 'Покажи селектора на колони', @@ -26,7 +26,13 @@ const bgBGGrid: Partial = { toolbarFiltersTooltipShow: 'Покажи Филтрите', toolbarFiltersTooltipActive: (count) => `${count} активни филтри`, - // GridColumns panel text + // Export selector toolbar button text + // toolbarExport: 'Export', + // toolbarExportLabel: 'Export', + // toolbarExportCSV: 'Download as CSV', + // toolbarExportPrint: 'Print', + + // Columns panel text columnsPanelTextFieldLabel: 'Намери колона', columnsPanelTextFieldPlaceholder: 'Заглавие на колона', columnsPanelDragIconLabel: 'Пренареди на колона', @@ -40,6 +46,8 @@ const bgBGGrid: Partial = { filterPanelOperatorAnd: 'И', filterPanelOperatorOr: 'Или', filterPanelColumns: 'Колони', + filterPanelInputLabel: 'Стойност', + filterPanelInputPlaceholder: 'Стойност на филтъра', // Filter operators text filterOperatorContains: 'съдържа', @@ -52,11 +60,14 @@ const bgBGGrid: Partial = { filterOperatorOnOrAfter: 'е на или след', filterOperatorBefore: 'е преди', filterOperatorOnOrBefore: 'е на или преди', - filterPanelInputLabel: 'Стойност', - filterPanelInputPlaceholder: 'Стойност на филтъра', // filterOperatorIsEmpty: 'is empty', // filterOperatorIsNotEmpty: 'is not empty', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Меню', columnMenuShowColumns: 'Покажи колоните', @@ -81,8 +92,17 @@ const bgBGGrid: Partial = { footerTotalRows: 'Общо Rедове:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + + // Actions cell more text + // actionsCellMore: 'more', }; export const bgBG: Localization = getGridLocalization(bgBGGrid, bgBGCore); diff --git a/packages/grid/_modules_/grid/locales/deDE.ts b/packages/grid/_modules_/grid/locales/deDE.ts index 884bb728e6ce0..55269947bd16e 100644 --- a/packages/grid/_modules_/grid/locales/deDE.ts +++ b/packages/grid/_modules_/grid/locales/deDE.ts @@ -31,6 +31,7 @@ const deDEGrid: Partial = { toolbarExport: 'Exportieren', toolbarExportLabel: 'Exportieren', toolbarExportCSV: 'Download als CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Finde Spalte', @@ -56,13 +57,18 @@ const deDEGrid: Partial = { filterOperatorEndsWith: 'endet mit', filterOperatorIs: 'ist', filterOperatorNot: 'ist nicht', + filterOperatorAfter: 'ist nach', filterOperatorOnOrAfter: 'ist an oder nach', filterOperatorBefore: 'ist vor', filterOperatorOnOrBefore: 'ist an oder vor', - filterOperatorAfter: 'ist nach', filterOperatorIsEmpty: 'ist leer', filterOperatorIsNotEmpty: 'ist nicht leer', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menü', columnMenuShowColumns: 'Zeige alle Spalten', @@ -91,6 +97,13 @@ const deDEGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} von ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text // actionsCellMore: 'more', }; diff --git a/packages/grid/_modules_/grid/locales/elGR.ts b/packages/grid/_modules_/grid/locales/elGR.ts index ad01cde24aabc..af385f89d9fcc 100644 --- a/packages/grid/_modules_/grid/locales/elGR.ts +++ b/packages/grid/_modules_/grid/locales/elGR.ts @@ -30,6 +30,7 @@ const elGRGrid: Partial = { toolbarExport: 'Εξαγωγή', toolbarExportLabel: 'Εξαγωγή', toolbarExportCSV: 'Λήψη ως CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Εύρεση στήλης', @@ -62,6 +63,11 @@ const elGRGrid: Partial = { filterOperatorIsEmpty: 'είναι κενό', filterOperatorIsNotEmpty: 'δεν είναι κενό', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Μενού', columnMenuShowColumns: 'Εμφάνιση στηλών', @@ -90,6 +96,13 @@ const elGRGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} από ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'περισσότερα', }; diff --git a/packages/grid/_modules_/grid/locales/esES.ts b/packages/grid/_modules_/grid/locales/esES.ts index 9bcc0cf5a413a..69d811608c112 100644 --- a/packages/grid/_modules_/grid/locales/esES.ts +++ b/packages/grid/_modules_/grid/locales/esES.ts @@ -31,6 +31,7 @@ const esESGrid: Partial = { toolbarExport: 'Exportar', toolbarExportLabel: 'Exportar', toolbarExportCSV: 'Descargar como CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Columna de búsqueda', @@ -63,6 +64,11 @@ const esESGrid: Partial = { filterOperatorIsEmpty: 'está vacío', filterOperatorIsNotEmpty: 'no esta vacío', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menú', columnMenuShowColumns: 'Mostrar columnas', @@ -91,6 +97,13 @@ const esESGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} de ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'más', }; diff --git a/packages/grid/_modules_/grid/locales/faIR.ts b/packages/grid/_modules_/grid/locales/faIR.ts index ed4b5cb4cfdec..1005881224771 100644 --- a/packages/grid/_modules_/grid/locales/faIR.ts +++ b/packages/grid/_modules_/grid/locales/faIR.ts @@ -31,6 +31,7 @@ const faIRGrid: Partial = { toolbarExport: 'خروجی', toolbarExportLabel: 'خروجی', toolbarExportCSV: 'دانلود به‌صورت CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'پیداکردن ستون', @@ -105,9 +106,6 @@ const faIRGrid: Partial = { // Actions cell more text actionsCellMore: 'بیشتر', - - // Used core components translation keys - MuiTablePagination: {}, }; export const faIR: Localization = getGridLocalization(faIRGrid, faIRCore); diff --git a/packages/grid/_modules_/grid/locales/frFR.ts b/packages/grid/_modules_/grid/locales/frFR.ts index acff50d71e1a5..28c983b9c3033 100644 --- a/packages/grid/_modules_/grid/locales/frFR.ts +++ b/packages/grid/_modules_/grid/locales/frFR.ts @@ -31,6 +31,7 @@ const frFRGrid: Partial = { toolbarExport: 'Exporter', toolbarExportLabel: 'Exporter', toolbarExportCSV: 'Télécharger en CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Chercher colonne', @@ -56,13 +57,18 @@ const frFRGrid: Partial = { filterOperatorEndsWith: 'se termine par', filterOperatorIs: 'est', filterOperatorNot: "n'est pas", - filterOperatorOnOrAfter: 'égal ou postérieur', filterOperatorAfter: 'postérieur', - filterOperatorOnOrBefore: 'égal ou antérieur', + filterOperatorOnOrAfter: 'égal ou postérieur', filterOperatorBefore: 'antérieur', + filterOperatorOnOrBefore: 'égal ou antérieur', filterOperatorIsEmpty: 'est vide', filterOperatorIsNotEmpty: "n'est pas vide", + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Afficher les colonnes', @@ -94,6 +100,10 @@ const frFRGrid: Partial = { // Checkbox selection text checkboxSelectionHeaderName: 'Sélection', + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'Plus', }; diff --git a/packages/grid/_modules_/grid/locales/heIL.ts b/packages/grid/_modules_/grid/locales/heIL.ts index fb164c5afc9cd..2825a8a9aa01e 100644 --- a/packages/grid/_modules_/grid/locales/heIL.ts +++ b/packages/grid/_modules_/grid/locales/heIL.ts @@ -49,11 +49,6 @@ const heILGrid: Partial = { filterPanelInputLabel: 'ערך', filterPanelInputPlaceholder: 'ערך מסנן', - // Filter values text - filterValueAny: 'כל ערך', - filterValueTrue: 'כן', - filterValueFalse: 'לא', - // Filter operators text filterOperatorContains: 'מכיל', filterOperatorEquals: 'שווה ל-', @@ -61,13 +56,18 @@ const heILGrid: Partial = { filterOperatorEndsWith: 'נגמר ב-', filterOperatorIs: 'הינו', filterOperatorNot: 'אינו', - filterOperatorOnOrAfter: 'אחרי', filterOperatorAfter: 'ב- או אחרי', + filterOperatorOnOrAfter: 'אחרי', filterOperatorBefore: 'לפני', filterOperatorOnOrBefore: 'ב- או לפני', filterOperatorIsEmpty: 'ריק', filterOperatorIsNotEmpty: 'אינו ריק', + // Filter values text + filterValueAny: 'כל ערך', + filterValueTrue: 'כן', + filterValueFalse: 'לא', + // Column menu text columnMenuLabel: 'תפריט', columnMenuShowColumns: 'הצג עמודות', diff --git a/packages/grid/_modules_/grid/locales/itIT.ts b/packages/grid/_modules_/grid/locales/itIT.ts index ab1a01c13ff08..dea8533d14bdc 100644 --- a/packages/grid/_modules_/grid/locales/itIT.ts +++ b/packages/grid/_modules_/grid/locales/itIT.ts @@ -31,6 +31,7 @@ const itITGrid: Partial = { toolbarExport: 'Esporta', toolbarExportLabel: 'Esporta', toolbarExportCSV: 'Esporta in CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Cerca colonna', @@ -56,13 +57,18 @@ const itITGrid: Partial = { filterOperatorEndsWith: 'termina per', filterOperatorIs: 'uguale a', filterOperatorNot: 'diversa da', - filterOperatorOnOrAfter: 'a partire dal', filterOperatorAfter: 'dopo il', - filterOperatorOnOrBefore: 'fino al', + filterOperatorOnOrAfter: 'a partire dal', filterOperatorBefore: 'prima del', + filterOperatorOnOrBefore: 'fino al', filterOperatorIsEmpty: 'è vuoto', filterOperatorIsNotEmpty: 'non è vuoto', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Mostra le colonne', @@ -94,6 +100,10 @@ const itITGrid: Partial = { // Checkbox selection text checkboxSelectionHeaderName: 'Seleziona', + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'più', }; diff --git a/packages/grid/_modules_/grid/locales/jaJP.ts b/packages/grid/_modules_/grid/locales/jaJP.ts index ef8ef648722f0..46c2a582bc3fa 100644 --- a/packages/grid/_modules_/grid/locales/jaJP.ts +++ b/packages/grid/_modules_/grid/locales/jaJP.ts @@ -30,6 +30,7 @@ const jaJPGrid: Partial = { toolbarExport: 'エクスポート', toolbarExportLabel: 'エクスポート', toolbarExportCSV: 'CSVダウンロード', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: '列検索', @@ -62,6 +63,11 @@ const jaJPGrid: Partial = { filterOperatorIsEmpty: '...空である', filterOperatorIsNotEmpty: '...空でない', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'メニュー', columnMenuShowColumns: '列表示', @@ -92,6 +98,9 @@ const jaJPGrid: Partial = { // Boolean cell text booleanCellTrueLabel: '真', booleanCellFalseLabel: '偽', + + // Actions cell more text + // actionsCellMore: 'more', }; export const jaJP: Localization = getGridLocalization(jaJPGrid, jaJPCore); diff --git a/packages/grid/_modules_/grid/locales/koKR.ts b/packages/grid/_modules_/grid/locales/koKR.ts index a5ac84290345c..8c9fddb38edf6 100644 --- a/packages/grid/_modules_/grid/locales/koKR.ts +++ b/packages/grid/_modules_/grid/locales/koKR.ts @@ -30,6 +30,7 @@ const koKRGrid: Partial = { toolbarExport: '내보내기', toolbarExportLabel: '내보내기', toolbarExportCSV: 'CSV다운로드', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: '열 검색', @@ -88,12 +89,17 @@ const koKRGrid: Partial = { footerTotalRows: '총 행수:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', // Boolean cell text booleanCellTrueLabel: '참', booleanCellFalseLabel: '거짓', + + // Actions cell more text + // actionsCellMore: 'more', }; export const koKR: Localization = getGridLocalization(koKRGrid, koKRCore); diff --git a/packages/grid/_modules_/grid/locales/nlNL.ts b/packages/grid/_modules_/grid/locales/nlNL.ts index ca4c086d1588e..ef35c49a6719b 100644 --- a/packages/grid/_modules_/grid/locales/nlNL.ts +++ b/packages/grid/_modules_/grid/locales/nlNL.ts @@ -31,6 +31,7 @@ const nlNLGrid: Partial = { // toolbarExport: 'Export', // toolbarExportLabel: 'Export', // toolbarExportCSV: 'Download as CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Zoek kolom', @@ -56,13 +57,18 @@ const nlNLGrid: Partial = { filterOperatorEndsWith: 'eindigt met', filterOperatorIs: 'is', filterOperatorNot: 'is niet', - filterOperatorOnOrAfter: 'is gelijk of er voor', filterOperatorAfter: 'is voor', - filterOperatorOnOrBefore: 'is gelijk of er na', + filterOperatorOnOrAfter: 'is gelijk of er voor', filterOperatorBefore: 'is na', + filterOperatorOnOrBefore: 'is gelijk of er na', // filterOperatorIsEmpty: 'is empty', // filterOperatorIsNotEmpty: 'is not empty', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Toon kolommen', @@ -88,8 +94,14 @@ const nlNLGrid: Partial = { footerTotalRows: 'Totaal:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', // Actions cell more text // actionsCellMore: 'more', diff --git a/packages/grid/_modules_/grid/locales/plPL.ts b/packages/grid/_modules_/grid/locales/plPL.ts index 2ef0cc2cb40c5..74af2105332ce 100644 --- a/packages/grid/_modules_/grid/locales/plPL.ts +++ b/packages/grid/_modules_/grid/locales/plPL.ts @@ -30,6 +30,7 @@ const plPLGrid: Partial = { toolbarExport: 'Eksportuj', toolbarExportLabel: 'Eksportuj', toolbarExportCSV: 'Pobierz jako plik CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Znajdź kolumnę', @@ -62,6 +63,11 @@ const plPLGrid: Partial = { filterOperatorIsEmpty: 'jest pusty', filterOperatorIsNotEmpty: 'nie jest pusty', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Pokaż wszystkie kolumny', @@ -86,6 +92,13 @@ const plPLGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} z ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'więcej', }; diff --git a/packages/grid/_modules_/grid/locales/ptBR.ts b/packages/grid/_modules_/grid/locales/ptBR.ts index fec7249de6752..4bf6e92b0337e 100644 --- a/packages/grid/_modules_/grid/locales/ptBR.ts +++ b/packages/grid/_modules_/grid/locales/ptBR.ts @@ -31,6 +31,7 @@ const ptBRGrid: Partial = { toolbarExport: 'Exportar', toolbarExportLabel: 'Exportar', toolbarExportCSV: 'Baixar como CSV', + toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Localizar coluna', @@ -56,13 +57,18 @@ const ptBRGrid: Partial = { filterOperatorEndsWith: 'termina com', filterOperatorIs: 'é', filterOperatorNot: 'não é', + filterOperatorAfter: 'após', filterOperatorOnOrAfter: 'em ou após', filterOperatorBefore: 'antes de', filterOperatorOnOrBefore: 'em ou antes de', - filterOperatorAfter: 'após', filterOperatorIsEmpty: 'está vazio', filterOperatorIsNotEmpty: 'não está vazio', + // Filter values text + filterValueAny: 'any', + filterValueTrue: 'true', + filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Exibir colunas', diff --git a/packages/grid/_modules_/grid/locales/ruRU.ts b/packages/grid/_modules_/grid/locales/ruRU.ts index 9cacf34314a40..feae531068822 100644 --- a/packages/grid/_modules_/grid/locales/ruRU.ts +++ b/packages/grid/_modules_/grid/locales/ruRU.ts @@ -5,6 +5,7 @@ import { getGridLocalization, Localization } from '../utils/getGridLocalization' const ruRUGrid: Partial = { // Root noRowsLabel: 'Нет строк', + // noResultsOverlayLabel: 'No results found.', errorOverlayDefaultLabel: 'Обнаружена ошибка.', // Density selector toolbar button text @@ -40,6 +41,7 @@ const ruRUGrid: Partial = { toolbarExport: 'Экспорт', toolbarExportLabel: 'Экспорт', toolbarExportCSV: 'Скачать в формате CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Найти столбец', @@ -120,8 +122,7 @@ const ruRUGrid: Partial = { footerTotalRows: 'Всего строк:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, // Checkbox selection text checkboxSelectionHeaderName: 'Выбор флажка', diff --git a/packages/grid/_modules_/grid/locales/skSK.ts b/packages/grid/_modules_/grid/locales/skSK.ts index 74c94b46b1552..2df9f63784110 100644 --- a/packages/grid/_modules_/grid/locales/skSK.ts +++ b/packages/grid/_modules_/grid/locales/skSK.ts @@ -26,11 +26,13 @@ const skSKGrid: Partial = { toolbarFiltersTooltipShow: 'Zobraziť filtre', toolbarFiltersTooltipActive: (count) => { let pluralForm = 'aktívnych filtrov'; + if (count > 1 && count < 5) { pluralForm = 'aktívne filtre'; } else if (count === 1) { pluralForm = 'aktívny filter'; } + return `${count} ${pluralForm}`; }, @@ -38,6 +40,7 @@ const skSKGrid: Partial = { toolbarExport: 'Export', toolbarExportLabel: 'Export', toolbarExportCSV: 'Stiahnuť ako CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Nájsť stĺpec', @@ -87,11 +90,13 @@ const skSKGrid: Partial = { // Column header text columnHeaderFiltersTooltipActive: (count) => { let pluralForm = 'aktívnych filtrov'; + if (count > 1 && count < 5) { pluralForm = 'aktívne filtre'; } else if (count === 1) { pluralForm = 'aktívny filter'; } + return `${count} ${pluralForm}`; }, columnHeaderFiltersLabel: 'Zobraziť filtre', @@ -100,11 +105,13 @@ const skSKGrid: Partial = { // Rows selected footer text footerRowSelected: (count) => { let pluralForm = 'vybraných záznamov'; + if (count > 1 && count < 5) { pluralForm = 'vybrané záznamy'; } else if (count === 1) { pluralForm = 'vybraný záznam'; } + return `${count} ${pluralForm}`; }, @@ -112,8 +119,7 @@ const skSKGrid: Partial = { footerTotalRows: 'Riadkov spolu:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, // Checkbox selection text checkboxSelectionHeaderName: 'Výber riadku', diff --git a/packages/grid/_modules_/grid/locales/trTR.ts b/packages/grid/_modules_/grid/locales/trTR.ts index e960e5d0643ac..e22f347a27702 100644 --- a/packages/grid/_modules_/grid/locales/trTR.ts +++ b/packages/grid/_modules_/grid/locales/trTR.ts @@ -5,6 +5,7 @@ import { getGridLocalization, Localization } from '../utils/getGridLocalization' const trTRGrid: Partial = { // Root noRowsLabel: 'Satır yok', + // noResultsOverlayLabel: 'No results found.', errorOverlayDefaultLabel: 'Bir hata oluştu.', // Density selector toolbar button text @@ -29,6 +30,7 @@ const trTRGrid: Partial = { toolbarExport: 'Dışa aktar', toolbarExportLabel: 'Dışa aktar', toolbarExportCSV: 'CSV olarak aktar', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Sütun ara', @@ -61,6 +63,11 @@ const trTRGrid: Partial = { filterOperatorIsEmpty: 'boş', filterOperatorIsNotEmpty: 'dolu', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Menü', columnMenuShowColumns: 'Sütunları göster', @@ -85,6 +92,13 @@ const trTRGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} / ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text // actionsCellMore: 'more', }; diff --git a/packages/grid/_modules_/grid/locales/ukUA.ts b/packages/grid/_modules_/grid/locales/ukUA.ts index 10a3521a10fb2..be75568304c4b 100644 --- a/packages/grid/_modules_/grid/locales/ukUA.ts +++ b/packages/grid/_modules_/grid/locales/ukUA.ts @@ -31,6 +31,7 @@ const ukUAGrid: Partial = { toolbarExport: 'Експорт', toolbarExportLabel: 'Експорт', toolbarExportCSV: 'Завантажити у форматі CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Знайти стовпець', @@ -93,8 +94,7 @@ const ukUAGrid: Partial = { footerTotalRows: 'Всього рядків:', // Total visible rows footer text - // footerTotalVisibleRows: (visibleCount, totalCount) => - // `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, + // footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} of ${totalCount.toLocaleString()}`, // Checkbox selection text checkboxSelectionHeaderName: 'Вибір прапорця', diff --git a/packages/grid/_modules_/grid/locales/viVN.ts b/packages/grid/_modules_/grid/locales/viVN.ts index 5756d9aeafcb8..ca0ddc357388b 100644 --- a/packages/grid/_modules_/grid/locales/viVN.ts +++ b/packages/grid/_modules_/grid/locales/viVN.ts @@ -31,6 +31,7 @@ const viVNGrid: Partial = { toolbarExport: 'Xuất', toolbarExportLabel: 'Xuất', toolbarExportCSV: 'Xuất CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: 'Tìm kiếm', @@ -63,6 +64,11 @@ const viVNGrid: Partial = { filterOperatorIsEmpty: 'Rỗng', filterOperatorIsNotEmpty: 'Khác rỗng', + // Filter values text + // filterValueAny: 'any', + // filterValueTrue: 'true', + // filterValueFalse: 'false', + // Column menu text columnMenuLabel: 'Danh mục', columnMenuShowColumns: 'Danh sách cột', @@ -89,6 +95,13 @@ const viVNGrid: Partial = { footerTotalVisibleRows: (visibleCount, totalCount) => `${visibleCount.toLocaleString()} / ${totalCount.toLocaleString()}`, + // Checkbox selection text + // checkboxSelectionHeaderName: 'Checkbox selection', + + // Boolean cell text + // booleanCellTrueLabel: 'true', + // booleanCellFalseLabel: 'false', + // Actions cell more text actionsCellMore: 'Thêm', }; diff --git a/packages/grid/_modules_/grid/locales/zhCN.ts b/packages/grid/_modules_/grid/locales/zhCN.ts index d39090af5ade4..d3f1e69ab702d 100644 --- a/packages/grid/_modules_/grid/locales/zhCN.ts +++ b/packages/grid/_modules_/grid/locales/zhCN.ts @@ -30,6 +30,7 @@ const zhCNGrid: Partial = { toolbarExport: '导出', toolbarExportLabel: '导出', toolbarExportCSV: '导出至CSV', + // toolbarExportPrint: 'Print', // Columns panel text columnsPanelTextFieldLabel: '搜索列', @@ -99,8 +100,8 @@ const zhCNGrid: Partial = { booleanCellTrueLabel: '真', booleanCellFalseLabel: '假', - // Used core components translation keys - MuiTablePagination: {}, + // Actions cell more text + // actionsCellMore: 'more', }; export const zhCN: Localization = getGridLocalization(zhCNGrid, zhCNCore); diff --git a/scripts/i18n.ts b/scripts/i18n.ts new file mode 100644 index 0000000000000..cdd1de7860819 --- /dev/null +++ b/scripts/i18n.ts @@ -0,0 +1,307 @@ +import * as fse from 'fs-extra'; +import * as path from 'path'; +import { exec } from 'child_process'; +import traverse from '@babel/traverse'; +import * as prettier from 'prettier'; +import * as babel from '@babel/core'; +import * as babelTypes from '@babel/types'; +import * as yargs from 'yargs'; + +const SOURCE_CODE_REPO = 'https://github.com/mui-org/material-ui-x'; + +const BABEL_PLUGINS = [require.resolve('@babel/plugin-syntax-typescript')]; + +type Translations = Record; + +type TranslationsByGroup = Record; + +function git(args: any) { + return new Promise((resolve, reject) => { + exec(`git ${args}`, (err, stdout) => { + if (err) { + reject(err); + } else { + resolve(stdout.trim()); + } + }); + }); +} + +function plugin(existingTranslations: Translations): babel.PluginObj { + return { + visitor: { + VariableDeclarator: { + enter(visitorPath) { + const { node } = visitorPath; + + if (!babelTypes.isIdentifier(node.id)) { + visitorPath.skip(); + return; + } + + // Test if the variable name follows the pattern xxXXGrid + if (!/[a-z]{2}[A-Z]{2}Grid/.test(node.id.name)) { + visitorPath.skip(); + return; + } + + // Mark this node as the one to replace later + (node as any).found = true; + + if (!babelTypes.isObjectExpression(node.init)) { + visitorPath.skip(); + return; + } + + node.init.properties.forEach((property) => { + if (!babelTypes.isObjectProperty(property) || !babelTypes.isIdentifier(property.key)) { + return; + } + const name = property.key.name; + existingTranslations[name] = property.value; + }); + }, + exit(visitorPath) { + const { node } = visitorPath; + + if (!(node as any).found) { + visitorPath.skip(); + return; + } + + visitorPath.get('init').replaceWith(babelTypes.identifier('_REPLACE_')); + }, + }, + }, + }; +} + +function extractTranslations(translationsPath: string): [TranslationsByGroup, Translations] { + const file = fse.readFileSync(translationsPath, { encoding: 'utf-8' }); + const ast = babel.parseSync(file, { + plugins: BABEL_PLUGINS, + configFile: false, + }); + + const translations: Translations = {}; + const translationsByGroup: TranslationsByGroup = {}; + + traverse(ast!, { + VariableDeclarator(visitorPath) { + const { node } = visitorPath; + + if (!node.init || !babelTypes.isObjectExpression(node.init)) { + visitorPath.skip(); + return; + } + + let group = 'No group'; + + node.init.properties.forEach((property) => { + if (!babelTypes.isObjectProperty(property)) { + return; + } + + const key = (property.key as babelTypes.Identifier).name; + + // Ignore translations for MUI Core components, e.g. MuiTablePagination + if (key.startsWith('Mui')) { + return; + } + + if (Array.isArray(property.leadingComments) && property.leadingComments.length > 0) { + group = property.leadingComments[0].value.trim(); + } + + if (!translationsByGroup[group]) { + translationsByGroup[group] = {}; + } + + translationsByGroup[group][key] = property.value; + translations[key] = property.value; + }); + }, + }); + + return [translationsByGroup, translations]; +} + +function findLocales(localesDirectory: string) { + const items = fse.readdirSync(localesDirectory); + const locales: any[] = []; + const localeRegex = /^[a-z]{2}[A-Z]{2}/; + + items.forEach((item) => { + const match = item.match(localeRegex); + if (!match) { + return; + } + + const localePath = path.resolve(localesDirectory, item); + const code = match[0]; + locales.push([localePath, code]); + }); + + return locales; +} + +function extractAndReplaceTranslations(localePath: string) { + const translations = {}; + const file = fse.readFileSync(localePath, { encoding: 'utf-8' }); + const { code } = babel.transformSync(file, { + plugins: [...BABEL_PLUGINS, plugin(translations)], + configFile: false, + retainLines: true, + })!; + return { translations, transformedCode: code, rawCode: file }; +} + +function injectTranslations( + code: string, + existingTranslations: Translations, + baseTranslations: TranslationsByGroup, +) { + const lines: string[] = []; + const astBuilder = babel.template(`const _ = %%value%%;`); + + Object.entries(baseTranslations).forEach(([group, translations]) => { + lines.push(`\n\n// ${group}`); + + Object.entries(translations).forEach(([key, value]) => { + const valueToTransform = existingTranslations[key] || value; + const ast = astBuilder({ value: valueToTransform }) as babelTypes.Statement; + const result = babel.transformFromAstSync(babelTypes.program([ast]), undefined, { + plugins: BABEL_PLUGINS, + configFile: false, + }); + + const valueAsCode = result!.code!.replace(/^const _ = (.*);/gs, '$1'); + const comment = !existingTranslations[key] ? '// ' : ''; + + lines.push(`${comment}${key}: ${valueAsCode},`); + }); + }); + + return code.replace('_REPLACE_', `{\n${lines.join('\n')}\n}`); +} + +// ISO 3166-1 alpha-2 +function countryToFlag(isoCode: string) { + return typeof String.fromCodePoint !== 'undefined' && isoCode + ? isoCode + .toUpperCase() + .replace(/./g, (char) => String.fromCodePoint(char.charCodeAt(0) + 127397)) + : isoCode; +} + +async function generateReport( + missingTranslations: Record, +) { + const lastCommitRef = await git('log -n 1 --pretty="format:%H"'); + const lines: string[] = []; + Object.entries(missingTranslations).forEach(([code, info]) => { + if (info.locations.length === 0) { + return; + } + lines.push(`### ${countryToFlag(code.slice(2))} ${code}`); + info.locations.forEach((location) => { + const permalink = `${SOURCE_CODE_REPO}/blob/${lastCommitRef}/${info.path}#L${location}`; + lines.push(permalink); + }); + }); + return lines.join('\n'); +} + +interface HandlerArgv { + report: boolean; +} + +async function run(argv: HandlerArgv) { + const { report } = argv; + const workspaceRoot = path.resolve(__dirname, '../'); + + const constantsPath = path.join( + workspaceRoot, + 'packages/grid/_modules_/grid/constants/localeTextConstants.ts', + ); + const [baseTranslationsByGroup, baseTranslations] = extractTranslations(constantsPath); + + const localesDirectory = path.resolve(workspaceRoot, 'packages/grid/_modules_/grid/locales'); + const locales = findLocales(localesDirectory); + + const missingTranslations: Record = {}; + + locales.forEach(([localePath, localeCode]) => { + const { + translations: existingTranslations, + transformedCode, + rawCode, + } = extractAndReplaceTranslations(localePath); + + if (!transformedCode || Object.keys(existingTranslations).length === 0) { + return; + } + + const codeWithNewTranslations = injectTranslations( + transformedCode, + existingTranslations, + baseTranslationsByGroup, + ); + + const prettierConfigPath = path.join(workspaceRoot, 'prettier.config.js'); + const prettierConfig = prettier.resolveConfig.sync(localePath, { config: prettierConfigPath }); + + const prettifiedCode = prettier.format(codeWithNewTranslations, { + ...prettierConfig, + filepath: localePath, + }); + + const lines = rawCode.split('\n'); + Object.entries(baseTranslations).forEach(([key]) => { + if (!existingTranslations[key]) { + if (!missingTranslations[localeCode]) { + missingTranslations[localeCode] = { + path: localePath.replace(workspaceRoot, '').slice(1), // Remove leading slash + locations: [], + }; + } + const location = lines.findIndex((line) => line.trim().startsWith(`// ${key}:`)); + // Ignore when both the translation and the placeholder are missing + if (location >= 0) { + missingTranslations[localeCode].locations.push(location + 1); + } + } + }); + + if (!report) { + fse.writeFileSync(localePath, prettifiedCode); + // eslint-disable-next-line no-console + console.log(`Wrote ${localeCode} locale.`); + } + }); + + if (report) { + // eslint-disable-next-line no-console + console.log(await generateReport(missingTranslations)); + } + + process.exit(0); +} + +yargs + .command({ + command: '$0', + describe: 'Syncs translation files.', + builder: (command) => { + return command.option('report', { + describe: "Don't write any file but generates a report with the missing translations.", + type: 'boolean', + default: false, + }); + }, + handler: run, + }) + .help() + .strict(true) + .version(false) + .parse(); diff --git a/yarn.lock b/yarn.lock index 074053114f87a..c894329422297 100644 --- a/yarn.lock +++ b/yarn.lock @@ -441,11 +441,21 @@ regenerator-runtime "^0.13.4" v8flags "^3.1.1" +"@babel/parser@^7.1.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.3.tgz#271bafcb811080905a119222edbc17909c82261d" + integrity sha512-dcNwU1O4sx57ClvLBVFbEgx0UZWfd0JQX5X6fxFRCLHelFBGXFfSz6Y0FAq2PEwUqlqLkdVjVr4VASEOuUnLJw== + "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.16.0", "@babel/parser@^7.8.3": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.0.tgz#cf147d7ada0a3655e79bf4b08ee846f00a00a295" integrity sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A== +"@babel/parser@^7.16.3": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" + integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng== + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a" @@ -1220,6 +1230,21 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.16.3": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787" + integrity sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.3" + "@babel/types" "^7.16.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" @@ -1228,7 +1253,7 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.11", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.16.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1": +"@babel/types@^7.0.0", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.11", "@babel/types@^7.12.13", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.16.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== @@ -4063,6 +4088,39 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== +"@types/babel__core@^7.1.16": + version "7.1.16" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" + integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" + integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" + integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + dependencies: + "@babel/types" "^7.3.0" + "@types/chai-dom@^0.0.11": version "0.0.11" resolved "https://registry.yarnpkg.com/@types/chai-dom/-/chai-dom-0.0.11.tgz#1058e77194560bd4d3117773602654e052cc2e0d"