From d27c0f382e782e4586f9352a8e4e29074224403b Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 14 May 2020 15:00:26 +0200 Subject: [PATCH] Added I18n --- package-lock.json | 68 ++++++++++++------- package.json | 1 + src/editor/Editor.jsx | 7 +- src/editor/widgets/comment/CommentWidget.jsx | 3 +- src/editor/widgets/comment/DropdownMenu.jsx | 5 +- src/editor/widgets/comment/TextEntryField.jsx | 3 +- src/editor/widgets/tag/TagWidget.jsx | 3 +- src/i18n/index.js | 10 +++ src/i18n/messages_de.json | 8 +++ src/index.js | 1 + 10 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 src/i18n/index.js create mode 100644 src/i18n/messages_de.json diff --git a/package-lock.json b/package-lock.json index 6f7f598..f5850ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@recogito/recogito-client-core", - "version": "0.1.4", + "version": "0.1.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2633,7 +2633,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -2968,7 +2967,6 @@ "version": "1.17.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -2987,7 +2985,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -3497,6 +3494,14 @@ "debug": "=3.1.0" } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -4187,8 +4192,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gauge": { "version": "2.7.4", @@ -4409,7 +4413,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -4432,8 +4435,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-unicode": { "version": "2.0.1", @@ -4842,8 +4844,7 @@ "is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" }, "is-data-descriptor": { "version": "0.1.4", @@ -4868,8 +4869,7 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-descriptor": { "version": "0.1.6", @@ -4983,7 +4983,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -4998,7 +4997,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -6074,6 +6072,17 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, + "node-polyglot": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/node-polyglot/-/node-polyglot-2.4.0.tgz", + "integrity": "sha512-KRzKwzMWm3wSAjOSop7/WwNyzaMkCe9ddkwXTQsIZEJmvEnqy/bCqLpAVw6xBszKfy4iLdYVA0d83L+cIkYPbA==", + "requires": { + "for-each": "^0.3.3", + "has": "^1.0.3", + "string.prototype.trim": "^1.1.2", + "warning": "^4.0.3" + } + }, "node-releases": { "version": "1.1.53", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", @@ -6231,8 +6240,7 @@ "object-inspect": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-is": { "version": "1.0.2", @@ -6243,8 +6251,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -6259,7 +6266,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -8204,11 +8210,20 @@ "strip-ansi": "^3.0.0" } }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, "string.prototype.trimend": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz", "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -8218,7 +8233,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -8229,7 +8243,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -8240,7 +8253,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz", "integrity": "sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -8828,6 +8840,14 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", diff --git a/package.json b/package.json index 3ed9889..6c2f813 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ }, "dependencies": { "axios": "^0.19.0", + "node-polyglot": "^2.4.0", "preact": "^10.4.1", "react-contenteditable": "^3.3.3", "react-transition-group": "^4.3.0", diff --git a/src/editor/Editor.jsx b/src/editor/Editor.jsx index 560f52d..2aad0ce 100644 --- a/src/editor/Editor.jsx +++ b/src/editor/Editor.jsx @@ -1,6 +1,7 @@ import React from 'preact/compat'; import { useState, useRef, useEffect } from 'preact/hooks'; import setPosition from './setPosition'; +import i18n from '../i18n'; /** We need to compare bounds by value, not by object ref **/ const bounds = elem => { @@ -112,17 +113,17 @@ const Editor = props => {
+ onClick={props.onCancel}>{i18n.t('Close')}
) : (
+ onClick={props.onCancel}>{i18n.t('Cancel')} + onClick={onOk}>{i18n.t('Ok')}
)} diff --git a/src/editor/widgets/comment/CommentWidget.jsx b/src/editor/widgets/comment/CommentWidget.jsx index d78056a..ac1ed47 100644 --- a/src/editor/widgets/comment/CommentWidget.jsx +++ b/src/editor/widgets/comment/CommentWidget.jsx @@ -1,6 +1,7 @@ import React from 'preact/compat'; import Comment from './Comment'; import TextEntryField from './TextEntryField'; +import i18n from '../../../i18n'; /** * Comments are TextualBodies where the purpose field is either @@ -65,7 +66,7 @@ const CommentWidget = props => { 0 ? 'Add a reply...' : 'Add a comment...'} + placeholder={comments.length > 0 ? i18n.t('Add a reply...') : i18n.t('Add a comment...')} onChange={onEditReply} onSaveAndClose={() => props.onSaveAndClose()} /> diff --git a/src/editor/widgets/comment/DropdownMenu.jsx b/src/editor/widgets/comment/DropdownMenu.jsx index d2c934e..6c262e3 100644 --- a/src/editor/widgets/comment/DropdownMenu.jsx +++ b/src/editor/widgets/comment/DropdownMenu.jsx @@ -1,6 +1,7 @@ import React from 'preact/compat'; import { useRef } from 'preact/hooks'; import useClickOutside from '../../useClickOutside'; +import i18n from '../../../i18n'; const DropdownMenu = props => { @@ -11,8 +12,8 @@ const DropdownMenu = props => { return ( ) diff --git a/src/editor/widgets/comment/TextEntryField.jsx b/src/editor/widgets/comment/TextEntryField.jsx index 37bfd87..b386df5 100644 --- a/src/editor/widgets/comment/TextEntryField.jsx +++ b/src/editor/widgets/comment/TextEntryField.jsx @@ -1,5 +1,6 @@ import React, { Component } from 'preact/compat'; import ContentEditable from 'react-contenteditable'; +import i18n from '../../../i18n'; /** * A basic text entry field, for reuse in different widgets. @@ -28,7 +29,7 @@ export default class TextEntryField extends Component { innerRef={this.onRender} className="r6o-editable-text" html={this.props.content} - data-placeholder={this.props.placeholder || "Add a comment..."} + data-placeholder={this.props.placeholder || i18n.t('Add a comment...')} disabled={!this.props.editable} onChange={this.props.onChange} onKeyDown={this.onKeyDown} /> diff --git a/src/editor/widgets/tag/TagWidget.jsx b/src/editor/widgets/tag/TagWidget.jsx index 1674394..a13291d 100644 --- a/src/editor/widgets/tag/TagWidget.jsx +++ b/src/editor/widgets/tag/TagWidget.jsx @@ -2,6 +2,7 @@ import React from 'preact/compat'; import { useState } from 'preact/hooks'; import { CSSTransition } from 'react-transition-group'; import { CloseIcon } from '../../../Icons'; +import i18n from '../../../i18n'; /** The basic freetext tag control from original Recogito **/ const TagWidget = props => { @@ -58,7 +59,7 @@ const TagWidget = props => { value={newTag} onChange={evt => setNewTag(evt.target.value)} onKeyDown={onKeyDown} - placeholder="Add tag..." /> + placeholder={i18n.t('Add tag...')} /> } ) diff --git a/src/i18n/index.js b/src/i18n/index.js new file mode 100644 index 0000000..4df2baa --- /dev/null +++ b/src/i18n/index.js @@ -0,0 +1,10 @@ +import * as Polyglot from 'node-polyglot'; + +const i18n = new Polyglot({ allowMissing: true }); + +i18n.init = lang => { + i18n.locale(lang); + i18n.extend(require(`./messages_${lang}.json`)); +} + +export default i18n; \ No newline at end of file diff --git a/src/i18n/messages_de.json b/src/i18n/messages_de.json new file mode 100644 index 0000000..d294c4e --- /dev/null +++ b/src/i18n/messages_de.json @@ -0,0 +1,8 @@ +{ + "Ok": "Ok", + "Cancel": "Abbrechen", + "Close": "Schliessen", + "Add a comment...": "Kommentar schreiben...", + "Add a reply...": "Antwort schreiben...", + "Add tag...": "Tag..." +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 2829134..201c24f 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,7 @@ export { default as WebAnnotation } from './WebAnnotation'; export * from './editor'; export * from './highlighter'; +export * from './i18n'; export * from './relations'; export * from './selection'; export * from './utils';