Skip to content
This repository has been archived by the owner on Dec 10, 2021. It is now read-only.

Add @superset-ui/translation #12

Merged
merged 10 commits into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions packages/superset-ui-translation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## `@superset-ui/translation`

[![Version](https://img.shields.io/npm/v/@superset-ui/translation.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/translation.svg?style=flat)

`i18n` locales and translation for Superset

### SupersetTranslation

#### Example usage

```js
import { configure, t } from '@superset-ui/translation';

configure({
languagePack: {...},
});

console.log(t('text to be translated'));
```

#### API

`configure({ [languagePack] })`

- Initialize the translator
- Initialize with the default language if no `languagePack` is specified.

`t(text[, args])`

- Translate `text` when no `args` is provided.
- Translate `text` and substitute `args` into the placeholders specified within `text`.

For example

```js
t('Hello %(name)s', user)
```

See [sprintf-js](/~https://github.com/alexei/sprintf.js) for more details on how to define placeholders.

### Development

`@data-ui/build-config` is used to manage the build configuration for this package including babel
builds, jest testing, eslint, and prettier.
71 changes: 71 additions & 0 deletions packages/superset-ui-translation/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "@superset-ui/translation",
"version": "0.0.0",
"description": "Superset UI translation",
"sideEffects": false,
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"scripts": {
"build:cjs": "beemo babel ./src --out-dir lib/ --minify",
"build:esm": "beemo babel ./src --out-dir esm/ --esm --minify",
"build": "yarn run build:cjs && yarn run build:esm",
"dev": "beemo babel --watch ./src --out-dir esm/ --esm",
"jest": "beemo jest --color --coverage",
"eslint": "beemo eslint \"./{src,test}/**/*.{js,jsx,json,md}\"",
"lint": "yarn run prettier && yarn run eslint",
"lint:fix": "yarn run prettier --write && yarn run eslint --fix",
"test": "yarn run jest",
"prettier": "beemo prettier \"./{src,test}/**/*.{js,jsx,json,md}\"",
"prepublish": "yarn run build"
},
"repository": {
"type": "git",
"url": "git+/~https://github.com/apache-superset/superset-ui.git"
},
"keywords": [
"superset",
"client",
"translation"
],
"author": "",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what to do about these. whoever inits the package could put their name, or maybe we can omit the field in package.jsons to make it a non-issue πŸ€”

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll put Superset for now.

"license": "Apache-2.0",
"bugs": {
"url": "/~https://github.com/apache-superset/superset-ui/issues"
},
"homepage": "/~https://github.com/apache-superset/superset-ui#readme",
"devDependencies": {
"@data-ui/build-config": "^0.0.23",
"react": "^16.4.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react devDependency + peerDependency can go away now right? πŸŽ‰

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

},
"dependencies": {
"@babel/runtime": "^7.1.2",
"jed": "^1.1.1",
"sprintf-js": "^1.1.1"
},
"peerDependencies": {
"react": "^16.4.1"
},
"beemo": {
"module": "@data-ui/build-config",
"drivers": [
"babel",
"eslint",
{
"driver": "jest",
"env": {
"NODE_ENV": "test"
}
},
"prettier"
],
"eslint": {
Copy link
Contributor

@williaster williaster Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a big deal since my PR is moving this config to the root but you can prob remove the app-specific beemo eslint config here for this since this was for the promises in @superset-ui/core

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool

"rules": {
"prefer-promise-reject-errors": "off"
}
}
}
}
29 changes: 29 additions & 0 deletions packages/superset-ui-translation/src/Translator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Jed from 'jed';
import { sprintf } from 'sprintf-js';

const DEFAULT_LANGUAGE_PACK = {
domain: 'superset',
locale_data: {
superset: {
'': {
domain: 'superset',
lang: 'en',
plural_forms: 'nplurals=1; plural=0',
},
},
},
};

export default class Translator {
constructor({ languagePack = DEFAULT_LANGUAGE_PACK } = {}) {
kristw marked this conversation as resolved.
Show resolved Hide resolved
this.i18n = new Jed(languagePack);
}

translate(input, ...args) {
if (input === null || input === undefined) {
return input;
}
const text = this.i18n.gettext(input);
return (args.length > 0) ? sprintf(text, ...args) : text;
}
}
21 changes: 21 additions & 0 deletions packages/superset-ui-translation/src/TranslatorSingleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Translator from './Translator';

let singleton;

function configure(config) {
singleton = new Translator(config);
return singleton;
};

function getInstance() {
if (!singleton) {
throw new Error('You must call configure(...) before calling other methods');
}
return singleton;
}

function t(...args) {
return getInstance().translate(...args);
}

export { configure, t };
1 change: 1 addition & 0 deletions packages/superset-ui-translation/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { configure, t } from './TranslatorSingleton';
38 changes: 38 additions & 0 deletions packages/superset-ui-translation/test/Translator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Translator from '../src/Translator';
import languagePackZh from './languagePacks/zh.json';

describe('Translator', () => {
it('exists', () => {
expect(Translator).toBeDefined();
});
describe('new Translator(config)', () => {
it('initializes when config is not specified', () => {
expect(new Translator()).toBeInstanceOf(Translator);
});
it('initializes when config is an empty object', () => {
expect(new Translator({})).toBeInstanceOf(Translator);
});
it('initializes when config is specified', () => {
expect(new Translator({
languagePack: languagePackZh,
})).toBeInstanceOf(Translator);
});
});
describe('.translate(input, ...args)', () => {
const translator = new Translator({
languagePack: languagePackZh,
});
it('returns null for null input', () => {
expect(translator.translate(null)).toBeNull();
});
it('returns undefined for undefined input', () => {
expect(translator.translate(undefined)).toBeUndefined();
});
it('translates simple text', () => {
expect(translator.translate('second')).toEqual('η§’');
});
it('translates template text with arguments', () => {
expect(translator.translate('Copy of %s', 1)).toEqual('1 ηš„ε‰―ζœ¬');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Translator from '../src/Translator';
import { configure, t } from '../src/TranslatorSingleton';
import languagePackZh from './languagePacks/zh.json';

describe('TranslatorSingleton', () => {
describe('before configure()', () => {
describe('t()', () => {
it('throws error', () => {
expect(() => t('second')).toThrow();
});
});
});
describe('after configure()', () => {
describe('configure()', () => {
it('creates and returns a translator', () => {
expect(configure()).toBeInstanceOf(Translator);
});
});
describe('t()', () => {
it('after configure() returns translated text', () => {
configure({
languagePack: languagePackZh,
});
expect(t('second')).toEqual('η§’');
});
});
});
});
12 changes: 12 additions & 0 deletions packages/superset-ui-translation/test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { configure, t } from '../src/index';

describe('index', () => {
it('exports configure()', () => {
expect(configure).toBeDefined();
expect(configure).toBeInstanceOf(Function);
});
it('exports t()', () => {
expect(t).toBeDefined();
expect(t).toBeInstanceOf(Function);
});
});
14 changes: 14 additions & 0 deletions packages/superset-ui-translation/test/languagePacks/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"domain": "superset",
"locale_data": {
"superset": {
"": {
"domain": "superset",
"plural_forms": "nplurals=2; plural=(n != 1)",
"lang": "en"
},
"second": [""],
"Copy of %s": [""]
}
}
}
14 changes: 14 additions & 0 deletions packages/superset-ui-translation/test/languagePacks/zh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"domain": "superset",
"locale_data": {
"superset": {
"": {
"domain": "superset",
"plural_forms": "nplurals=1; plural=0",
"lang": "zh"
},
"second": ["η§’"],
"Copy of %s": ["%s ηš„ε‰―ζœ¬"]
}
}
}