forked from TYPO3/typo3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TASK] Include and load CKEditor locales if configured
This patch adds support for loading the base CKEditor 5 locales and importing them in the backend if requested. Because CKEditor doesn't ship a full set of locales, we needed to add an additional build step that assembles the locales of all plugins we have installed. Resolves: #100873 Releases: main, 12.4 Change-Id: I971bf3e55d006a4a378123e8723c1bb8d23b09d1 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79026 Reviewed-by: Andreas Nedbal <[email protected]> Reviewed-by: Torben Hansen <[email protected]> Tested-by: Andreas Fernandez <[email protected]> Reviewed-by: Oliver Hader <[email protected]> Tested-by: core-ci <[email protected]> Reviewed-by: Andreas Fernandez <[email protected]> Tested-by: Andreas Nedbal <[email protected]> Tested-by: Torben Hansen <[email protected]> Tested-by: Oliver Hader <[email protected]>
- Loading branch information
Showing
79 changed files
with
269 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
const { resolve, join } = require('path') | ||
const { readdirSync, existsSync, readFileSync, mkdirSync, writeFileSync } = require('fs') | ||
const PO = require('pofile') | ||
|
||
/** | ||
* This script assembles full locales from all plugins found in node_modules/@ckeditor/ | ||
* | ||
* Parts of this script are based on @ckeditor/ckeditor5-dev-translations/lib/multiplelanguagetranslationservice.js | ||
* | ||
* Subject to following license terms: | ||
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see @ckeditor/ckeditor5-dev-translations/LICENSE.md. | ||
*/ | ||
|
||
const _languages = new Set(); | ||
const _translationDictionaries = {}; | ||
const _pluralFormsRules = {}; | ||
|
||
function loadPackage(packagePath) { | ||
if (!existsSync(packagePath)) { | ||
return; | ||
} | ||
|
||
const translationPath = getTranslationPath(packagePath); | ||
|
||
if (!existsSync(translationPath)) { | ||
return; | ||
} | ||
|
||
for (const fileName of readdirSync(translationPath)) { | ||
if (!fileName.endsWith('.po') ) { | ||
continue; | ||
} | ||
|
||
const language = fileName.replace( /\.po$/, '' ); | ||
const pathToPoFile = join(translationPath, fileName); | ||
|
||
_languages.add(language); | ||
loadPoFile(language, pathToPoFile); | ||
} | ||
} | ||
|
||
function getTranslationPath(packagePath) { | ||
return join(packagePath, 'lang', 'translations'); | ||
} | ||
|
||
function loadPoFile(language, pathToPoFile) { | ||
if (!existsSync(pathToPoFile)) { | ||
return; | ||
} | ||
|
||
const parsedTranslationFile = PO.parse(readFileSync(pathToPoFile, 'utf-8')); | ||
|
||
_pluralFormsRules[language] = _pluralFormsRules[language] || parsedTranslationFile.headers['Plural-Forms']; | ||
|
||
if (!_translationDictionaries[language]) { | ||
_translationDictionaries[language] = {}; | ||
} | ||
|
||
const dictionary = _translationDictionaries[language]; | ||
|
||
for (const item of parsedTranslationFile.items) { | ||
dictionary[item.msgid] = item.msgstr; | ||
} | ||
} | ||
|
||
function getTranslationAssets(outputDirectory, languages) { | ||
return languages.map(language => { | ||
const outputPath = join(outputDirectory, `${language}.js`); | ||
|
||
if ( !_translationDictionaries[language]) { | ||
return { outputBody: '', outputPath }; | ||
} | ||
|
||
const translations = getTranslations(language); | ||
|
||
// Examples of plural forms: | ||
// pluralForms="nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2)" | ||
// pluralForms="nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2" | ||
|
||
/** @type {String} */ | ||
const pluralFormsRule = _pluralFormsRules[language]; | ||
|
||
let pluralFormFunction; | ||
|
||
|
||
if (!pluralFormsRule) { | ||
|
||
} else { | ||
const pluralFormFunctionBodyMatch = pluralFormsRule.match(/(?:plural=)(.+)/); | ||
|
||
// Add support for ES5 - this function will not be transpiled. | ||
pluralFormFunction = `function(n){return ${pluralFormFunctionBodyMatch[1]};}`; | ||
} | ||
|
||
// Stringify translations and remove unnecessary `""` around property names. | ||
const stringifiedTranslations = JSON.stringify(translations) | ||
.replace(/"([\w_]+)":/g, '$1:'); | ||
|
||
const outputBody = ( | ||
'(function(d){' + | ||
` const l = d['${language}'] = d['${language}'] || {};` + | ||
' l.dictionary=Object.assign(' + | ||
' l.dictionary||{},' + | ||
` ${stringifiedTranslations}` + | ||
' );' + | ||
(pluralFormFunction ? `l.getPluralForm=${pluralFormFunction};` : '' ) + | ||
'})(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));' | ||
); | ||
|
||
return { outputBody, outputPath }; | ||
}); | ||
} | ||
|
||
function getTranslations(language) { | ||
const langDictionary = _translationDictionaries[language]; | ||
const translatedStrings = {}; | ||
|
||
for ( const messageId of Object.keys(langDictionary)) { | ||
const translatedMessage = langDictionary[messageId]; | ||
|
||
// Register first form as a default form if only one form was provided. | ||
translatedStrings[messageId] = translatedMessage.length > 1 ? | ||
translatedMessage : | ||
translatedMessage[0]; | ||
} | ||
|
||
return translatedStrings; | ||
} | ||
|
||
const ckeditorNamespacePath = resolve('./node_modules/@ckeditor/'); | ||
for (const packagePath of readdirSync(ckeditorNamespacePath)) { | ||
loadPackage(`${ckeditorNamespacePath}/${packagePath}/`); | ||
} | ||
|
||
if (!existsSync('./ckeditorLocales/')) { | ||
mkdirSync('./ckeditorLocales/'); | ||
} | ||
|
||
const assets = getTranslationAssets('./ckeditorLocales/', Array.from(_languages)); | ||
|
||
for (const asset of assets) { | ||
if (asset.outputBody !== undefined) { | ||
writeFileSync(asset.outputPath, asset.outputBody); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { resolve, join } from 'path' | ||
import { readdirSync } from 'fs' | ||
|
||
/** | ||
* Helper function to build rollup bundling configuration for all existing | ||
* CKEditor translations | ||
*/ | ||
export function buildConfigForTranslations() { | ||
const translationPath = resolve('./ckeditorLocales/') | ||
const translationFiles = readdirSync(translationPath) | ||
const configuration = [] | ||
|
||
for (const translationFile of translationFiles) { | ||
configuration.push({ | ||
input: join(translationPath, translationFile), | ||
output: { | ||
compact: true, | ||
file: `../typo3/sysext/rte_ckeditor/Resources/Public/Contrib/translations/${translationFile}`, | ||
format: 'es', | ||
}, | ||
}) | ||
} | ||
|
||
return configuration | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
typo3/sysext/rte_ckeditor/Resources/Public/Contrib/translations/af.js
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
1 change: 1 addition & 0 deletions
1
typo3/sysext/rte_ckeditor/Resources/Public/Contrib/translations/ar.js
Large diffs are not rendered by default.
Oops, something went wrong.
1 change: 1 addition & 0 deletions
1
typo3/sysext/rte_ckeditor/Resources/Public/Contrib/translations/ast.js
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.