diff --git a/.tx/config b/.tx/config index d4c23592..86248033 100644 --- a/.tx/config +++ b/.tx/config @@ -6,21 +6,24 @@ # React-Invenio-Deposit is free software; you can redistribute it and/or modify it # under the terms of the MIT License; see LICENSE file for more details. -# -# 1) Extract translation keys/values, -# $ npm run i18n-scan -# 2) Update .pot file, this file is pushed to transifex -# $ npm run i18n-conv-json -# 3) Convert/update .json from .po -# $ npm run i18n-conv-po-all -# 4) Install the transifex-client +# +# 1) Add a new language +# npm run init_catalog lang +# 2) Extract translation keys/values +# $ npm run extract_messages +# 3) Install the transifex-client # $ pip install transifex-client -# 5) Push source (.pot) and translations (.po) to Transifex +# 4) Push source (.pot) and translations (.po) to Transifex # $ tx push -s -t -# 6) Pull translations for a single language from Transifex +# 5) Pull translations for a single language from Transifex # $ tx pull -l -# 7) Pull translations for all languages from Transifex +# 6) Pull translations for all languages from Transifex # $ tx pull -a +# 7) Compile .po files for all languages +# $ npm run compile_catalog +# 8) Convert .po file for a single language +# $ npm run compile_catalog lang + [main] host = https://www.transifex.com diff --git a/getTextConverter.js b/getTextConverter.js deleted file mode 100644 index 101165d8..00000000 --- a/getTextConverter.js +++ /dev/null @@ -1,24 +0,0 @@ -// This file is part of React-Invenio-Deposit -// Copyright (C) 2021 Graz University of Technology. -// -// React-Invenio-Deposit is free software; you can redistribute it and/or modify it -// under the terms of the MIT License; see LICENSE file for more details. - -const { readFileSync, writeFileSync } = require('fs'); -const { gettextToI18next } = require('i18next-conv'); -const { languages } = require('./package').config; - -// it accepts the same options as the cli. -// https://github.com/i18next/i18next-gettext-converter#options -const options = {/* you options here */} - -function save(target) { - return result => { - writeFileSync(target, result); - }; - } - -for (lang of languages) { -gettextToI18next(lang, readFileSync(`src/lib/translations/${lang}/messages.po`), options) -.then(save(`src/lib/translations/${lang}/translations.json`)); -} diff --git a/i18next-scanner.config.js b/i18next-scanner.config.js index 6fbb0c63..8e822235 100644 --- a/i18next-scanner.config.js +++ b/i18next-scanner.config.js @@ -4,66 +4,53 @@ // React-Invenio-Deposit is free software; you can redistribute it and/or modify it // under the terms of the MIT License; see LICENSE file for more details. -const fs = require('fs'); -const chalk = require('chalk'); const { languages } = require('./package').config; -// list of func used to +// list of func used to // mark the strings for translation -const funcList = ['i18next.t', 'i18n.t', 't']; +const funcList = ['i18next.t']; module.exports = { - options: { - debug: true, - browserLanguageDetection: true, - func: { - list: funcList, - extensions: ['.js', '.jsx'] - }, - trans: false, // Enable for using Trans component - lngs: languages, - ns: [ - // file name (.json) - 'translations', - ], - defaultLng: 'en', - defaultNs: 'translations', - resource: { - // The path where resources get loaded from. Relative to current working directory. - loadPath: 'src/lib/translations/{{lng}}/{{ns}}.json', - - // The path to store resources. - savePath: 'src/lib/translations/{{lng}}/{{ns}}.json', - - jsonIndent: 2, - lineEnding: '\n' - }, - nsSeparator: false, // namespace separator - - //Set to false to disable key separator - // if you prefer having keys as the fallback for translation (e.g. gettext). - keySeparator: false, + options: { + debug: true, + removeUnusedKeys: true, + browserLanguageDetection: true, + func: { + list: funcList, + extensions: ['.js', '.jsx'], }, + // trans: false, // Enable for using Trans component + lngs: languages, + ns: [ + // file name (.json) + 'translations', + ], + defaultLng: 'en', + defaultNs: 'translations', + // @param {string} lng The language currently used. + // @param {string} ns The namespace currently used. + // @param {string} key The translation key. + // @return {string} Returns a default value for the translation key. + defaultValue: function (lng, ns, key) { + if (lng === 'en') { + // Return key as the default value for English language + return key; + } + }, + resource: { + // The path where resources get loaded from. Relative to current working directory. + loadPath: 'src/lib/translations/messages/{{lng}}/{{ns}}.json', - // func is provided - // (if needed)for more custom extractions. - transform: function customTransform(file, enc, done) { - "use strict"; - const parser = this.parser; - const content = fs.readFileSync(file.path, enc); - let count = 0; + // The path to store resources. + savePath: 'src/lib/translations/messages/{{lng}}/{{ns}}.json', - parser.parseFuncFromString(content, { list: funcList }, (key, options) => { - parser.set(key, Object.assign({}, options, { - nsSeparator: false, - keySeparator: false - })); - ++count; - }); + jsonIndent: 2, + lineEnding: '\n', + }, + nsSeparator: false, // namespace separator - if (count > 0) { - console.log(`i18next-scanner: count=${chalk.cyan(count)}, file=${chalk.yellow(JSON.stringify(file.relative))}`); - } - done(); - } + //Set to false to disable key separator + // if you prefer having keys as the fallback for translation (e.g. gettext). + keySeparator: false, + }, }; diff --git a/package.json b/package.json index 4204c04b..d9f899b9 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,10 @@ "postlink-dist": "cd dist && rm -rf node_modules", "unlink-dist": "cd dist && npm unlink && rm package*", "watch": "NODE_ENV=development rollup --watch -c", - "i18n-scan": "i18next-scanner --config i18next-scanner.config.js src/**/*.{js,jsx}", - "i18n-conv-json": "i18next-conv -l en -s ./src/lib/translations/en/translations.json -t ./src/lib/translations/translations.pot", - "i18n-conv-po": "i18next-conv -l $npm_config_lang -s ./src/lib/translations/$npm_config_lang/messages.po -t ./src/lib/translations/$npm_config_lang/translations.json", - "i18n-conv-po-all": "node ./getTextConverter.js", + "extract_messages": "i18next-scanner --config i18next-scanner.config.js 'src/**/*.{js,jsx}'", + "postextract_messages": "i18next-conv -l en -s ./src/lib/translations/messages/en/translations.json -t ./src/lib/translations/translations.pot", + "compile_catalog": "node ./src/lib/translations/scripts/compileCatalog.js", + "init_catalog": "node ./src/lib/translations/scripts/initCatalog", "test": "react-scripts test", "eject": "react-scripts eject", "lint": "eslint src/**/*.js", @@ -35,6 +35,8 @@ }, "dependencies": {}, "peerDependencies": { + "@ckeditor/ckeditor5-build-classic": "^16.0.0", + "@ckeditor/ckeditor5-react": "^2.1.0", "axios": "^0.21.1", "formik": "^2.1.4", "react": "^16.13.1", @@ -136,4 +138,4 @@ "enzyme-to-json/serializer" ] } -} +} \ No newline at end of file diff --git a/src/lib/components/DepositFormTitle.js b/src/lib/components/DepositFormTitle.js index 0dd72ad9..87fda306 100644 --- a/src/lib/components/DepositFormTitle.js +++ b/src/lib/components/DepositFormTitle.js @@ -8,13 +8,15 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { Header } from 'semantic-ui-react'; -import i18next from '../i18next'; +import { i18next } from '../i18next'; class DepositFormTitleComponent extends Component { render() { let content = ''; if (!this.props.isPublished) { - content = this.props.isVersion ? i18next.t('New version') : i18next.t('New upload'); + content = this.props.isVersion + ? i18next.t('New version') + : i18next.t('New upload'); } else { content = i18next.t('Edit upload'); } diff --git a/src/lib/components/FileUploader/FileUploaderToolbar.js b/src/lib/components/FileUploader/FileUploaderToolbar.js index 51bc1210..9aa47774 100644 --- a/src/lib/components/FileUploader/FileUploaderToolbar.js +++ b/src/lib/components/FileUploader/FileUploaderToolbar.js @@ -9,7 +9,7 @@ import { useFormikContext } from 'formik'; import React from 'react'; import { Checkbox, Grid, Icon, Label, List, Popup } from 'semantic-ui-react'; import { humanReadableBytes } from './utils'; -import i18next from '../../i18next'; +import { i18next } from '../../i18next'; // NOTE: This component has to be a function component to allow // the `useFormikContext` hook. @@ -30,7 +30,7 @@ export const FileUploaderToolbar = ({ setFieldValue("files.enabled", !filesEnabled)} + onChange={() => setFieldValue('files.enabled', !filesEnabled)} disabled={filesList.length > 0} checked={!filesEnabled} /> diff --git a/src/lib/components/Identifiers/IdentifiersField.js b/src/lib/components/Identifiers/IdentifiersField.js index 2b2e530c..45cbf908 100644 --- a/src/lib/components/Identifiers/IdentifiersField.js +++ b/src/lib/components/Identifiers/IdentifiersField.js @@ -15,6 +15,7 @@ import { TextField, } from 'react-invenio-forms'; import { Button, Form } from 'semantic-ui-react'; +import { i18next } from '../../i18next'; import { emptyIdentifier } from '../../record'; /** Identifiers array component */ @@ -24,7 +25,7 @@ export class IdentifiersField extends Component { return ( <> { + const translationFile = await import( + `./translations/messages/${lang}/translations.json` + ); + return { + ...obj, + [lang]: translationFile, + }; + }, {}), + // specify language detection order + detection: { + order: ['htmlTag'], + // cache user language off + caches: [], + }, +}; // i18next instance creation // https://www.i18next.com/overview/api#instance-creation // this is required in order to keep the resources seperate -// if there is going to be another package +// if there is going to be another package // which requires translation this is the way to create a new instance. // // We can use this particular instance for this particular package // to mark strings for translation. -const i18next = i18n.createInstance(); -i18next - .use(LanguageDetector) - .init(options); -export default i18next; +export const i18next = i18n.createInstance(); +i18next.use(LanguageDetector).init(options); diff --git a/src/lib/translations/de/translations.json b/src/lib/translations/de/translations.json deleted file mode 100644 index 849d1cba..00000000 --- a/src/lib/translations/de/translations.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "New version": "Neue Version", - "New upload": "Neuer Upload", - "Edit upload": "Upload bearbeiten", - "Storage available": "Verfügbarer Speicherplatz" -} \ No newline at end of file diff --git a/src/lib/translations/en/translations.json b/src/lib/translations/en/translations.json deleted file mode 100644 index df4ef21b..00000000 --- a/src/lib/translations/en/translations.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "New version": "New version", - "New upload": "New upload", - "Edit upload": "Edit upload", - "Storage available": "Storage available" -} \ No newline at end of file diff --git a/src/lib/translations/de/messages.po b/src/lib/translations/messages/de/messages.po similarity index 100% rename from src/lib/translations/de/messages.po rename to src/lib/translations/messages/de/messages.po diff --git a/src/lib/translations/messages/de/translations.json b/src/lib/translations/messages/de/translations.json new file mode 100644 index 00000000..6af165a5 --- /dev/null +++ b/src/lib/translations/messages/de/translations.json @@ -0,0 +1,6 @@ +{ + "New version": "Neue Version", + "New upload": "Neuer Upload", + "Edit upload": "Upload bearbeiten", + "Storage available": "Verfügbarer Speicherplatz" +} diff --git a/src/lib/translations/en/messages.po b/src/lib/translations/messages/en/messages.po similarity index 100% rename from src/lib/translations/en/messages.po rename to src/lib/translations/messages/en/messages.po diff --git a/src/lib/translations/messages/en/translations.json b/src/lib/translations/messages/en/translations.json new file mode 100644 index 00000000..9bbdb331 --- /dev/null +++ b/src/lib/translations/messages/en/translations.json @@ -0,0 +1,7 @@ +{ + "New version": "New version", + "New upload": "New upload", + "Edit upload": "Edit upload", + "Storage available": "Storage available", + "Add identifier": "Add identifier" +} diff --git a/src/lib/translations/tr/messages.po b/src/lib/translations/messages/tr/messages.po similarity index 100% rename from src/lib/translations/tr/messages.po rename to src/lib/translations/messages/tr/messages.po diff --git a/src/lib/translations/messages/tr/translations.json b/src/lib/translations/messages/tr/translations.json new file mode 100644 index 00000000..c58237e8 --- /dev/null +++ b/src/lib/translations/messages/tr/translations.json @@ -0,0 +1,6 @@ +{ + "New version": "", + "New upload": "", + "Edit upload": "", + "Storage available": "" +} diff --git a/src/lib/translations/scripts/compileCatalog.js b/src/lib/translations/scripts/compileCatalog.js new file mode 100644 index 00000000..e058739d --- /dev/null +++ b/src/lib/translations/scripts/compileCatalog.js @@ -0,0 +1,38 @@ +// This file is part of React-Invenio-Deposit +// Copyright (C) 2021 Graz University of Technology. +// +// React-Invenio-Deposit is free software; you can redistribute it and/or modify it +// under the terms of the MIT License; see LICENSE file for more details. + +const { readFileSync, writeFileSync } = require('fs'); +const { gettextToI18next } = require('i18next-conv'); +const { languages } = require('./package').config; + +// it accepts the same options as the cli. +// https://github.com/i18next/i18next-gettext-converter#options +const options = { + /* you options here */ +}; + +function save(target) { + return (result) => { + writeFileSync(target, result); + }; +} + +if ('lang' === process.argv[2]) { + const lang = process.argv[3]; + gettextToI18next( + lang, + readFileSync(`src/lib/translations/${lang}/messages.po`), + options + ).then(save(`src/lib/translations/${lang}/translations.json`)); +} else { + for (const lang of languages) { + gettextToI18next( + lang, + readFileSync(`src/lib/translations/${lang}/messages.po`), + options + ).then(save(`src/lib/translations/${lang}/translations.json`)); + } +} diff --git a/src/lib/translations/scripts/initCatalog.js b/src/lib/translations/scripts/initCatalog.js new file mode 100644 index 00000000..601fe16d --- /dev/null +++ b/src/lib/translations/scripts/initCatalog.js @@ -0,0 +1,19 @@ +// This file is part of React-Invenio-Deposit +// Copyright (C) 2021 Graz University of Technology. +// +// React-Invenio-Deposit is free software; you can redistribute it and/or modify it +// under the terms of the MIT License; see LICENSE file for more details. + +const { writeFileSync } = require('fs'); +const packageJson = require('./package'); +const { languages } = packageJson.config; +if ('lang' in process.argv) { + const addedLang = process.argv[3]; + languages.push(addedLang); + packageJson.config.languages = [...new Set(languages)]; + writeFileSync(`package.json`, JSON.stringify(packageJson, null, 2)); +} else { + console.error( + 'Error:Please provide a language by running `npm run init_catalog lang `' + ); +} diff --git a/src/lib/translations/tr/translations.json b/src/lib/translations/tr/translations.json deleted file mode 100644 index 4fdd8bf4..00000000 --- a/src/lib/translations/tr/translations.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "New version": "", - "New upload": "", - "Edit upload": "", - "Storage available": "" -} \ No newline at end of file diff --git a/src/lib/translations/translations.pot b/src/lib/translations/translations.pot index a1bb9e21..104d2508 100644 --- a/src/lib/translations/translations.pot +++ b/src/lib/translations/translations.pot @@ -5,18 +5,21 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2021-06-29T13:05:15.622Z\n" -"PO-Revision-Date: 2021-06-29T13:05:15.622Z\n" +"POT-Creation-Date: 2021-07-05T16:43:32.397Z\n" +"PO-Revision-Date: 2021-07-05T16:43:32.397Z\n" "Language: en\n" msgid "New version" -msgstr "" +msgstr "New version" msgid "New upload" -msgstr "" +msgstr "New upload" msgid "Edit upload" -msgstr "" +msgstr "Edit upload" msgid "Storage available" -msgstr "" \ No newline at end of file +msgstr "Storage available" + +msgid "Add identifier" +msgstr "Add identifier" \ No newline at end of file