I'm sorry Typescript, it's not you...
This commit is contained in:
parent
7e79fc4c66
commit
255547914b
|
@ -1,13 +1,9 @@
|
|||
#root = true
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 100
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
|
@ -0,0 +1 @@
|
|||
/test/fixtures
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": ["standard", "prettier", "prettier/standard"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"jest": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"modules": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,3 @@
|
|||
node_modules
|
||||
coverage
|
||||
.nyc_output
|
||||
.DS_Store
|
||||
*.log
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
compiled
|
||||
.awcache
|
||||
.rpt2_cache
|
||||
docs
|
||||
dist/
|
|
@ -0,0 +1,4 @@
|
|||
/test/
|
||||
/.*
|
||||
/yarn.lock
|
||||
/package-lock.json
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"semi": false,
|
||||
"printWidth": 80,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"singleQuote": true
|
||||
}
|
19
.travis.yml
19
.travis.yml
|
@ -1,19 +0,0 @@
|
|||
language: node_js
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^greenkeeper/.*$/
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
notifications:
|
||||
email: false
|
||||
node_js:
|
||||
- node
|
||||
script:
|
||||
- npm run test:prod && npm run build
|
||||
after_success:
|
||||
- npm run report-coverage
|
||||
- npm run deploy-docs
|
||||
- npm run semantic-release
|
|
@ -1,17 +0,0 @@
|
|||
We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏
|
||||
|
||||
## Instructions
|
||||
|
||||
These steps will guide you through contributing to this project:
|
||||
|
||||
- Fork the repo
|
||||
- Clone it and install dependencies
|
||||
|
||||
git clone https://github.com/YOUR-USERNAME/typescript-library-starter
|
||||
npm install
|
||||
|
||||
Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them.
|
||||
|
||||
Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working.
|
||||
|
||||
Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit).
|
19
README.md
19
README.md
|
@ -53,10 +53,23 @@ i18n(store, [
|
|||
### On `templates`
|
||||
|
||||
```html
|
||||
|
||||
<div>
|
||||
{$_('message')}: {$_.upper('messages.success')}
|
||||
{$_('message')}: {upper($_('messages.success'))}
|
||||
</div>
|
||||
|
||||
<!-- Will render for en-US -->
|
||||
Message: SUCCESS
|
||||
<script>
|
||||
import { upper } from 'svelte-i18n';
|
||||
export default {
|
||||
helpers: {
|
||||
upper,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
Renders:
|
||||
|
||||
```html
|
||||
Message: SUCCESS
|
||||
```
|
|
@ -1,74 +0,0 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at alexjovermorales@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
File diff suppressed because it is too large
Load Diff
128
package.json
128
package.json
|
@ -1,114 +1,34 @@
|
|||
{
|
||||
"name": "svelte-i18n",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"main": "dist/svelte-i18n.umd.js",
|
||||
"module": "dist/svelte-i18n.es5.js",
|
||||
"typings": "dist/types/svelte-i18n.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"author": "Christian Kaisermann <christian@kaisermann.me>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"main": "dist/i18n.js",
|
||||
"types": "src/index.d.ts",
|
||||
"description": "",
|
||||
"author": "Christian Kaisermann <christian@kaisermann.me>",
|
||||
"repository": "https://github.com/kaisermann",
|
||||
"keywords": [],
|
||||
"scripts": {
|
||||
"lint": "tslint -t codeFrame 'src/**/*.ts' 'test/**/*.ts'",
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs --target es6 --theme minimal --mode file src",
|
||||
"start": "rollup -c rollup.config.ts -w",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:prod": "npm run lint && npm run test -- --coverage --no-cache",
|
||||
"deploy-docs": "ts-node tools/gh-pages-publish",
|
||||
"report-coverage": "cat ./coverage/lcov.info | coveralls",
|
||||
"commit": "git-cz",
|
||||
"semantic-release": "semantic-release",
|
||||
"semantic-release-prepare": "ts-node tools/semantic-release-prepare",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"{src,test}/**/*.ts": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-conventional-changelog"
|
||||
},
|
||||
"validate-commit-msg": {
|
||||
"types": "conventional-commit-types",
|
||||
"helpMessage": "Use \"npm run commit\" instead, we use conventional-changelog format :) (https://github.com/commitizen/cz-cli)"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
|
||||
},
|
||||
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js"
|
||||
],
|
||||
"coveragePathIgnorePatterns": [
|
||||
"/node_modules/",
|
||||
"/test/"
|
||||
],
|
||||
"coverageThreshold": {
|
||||
"global": {
|
||||
"branches": 90,
|
||||
"functions": 95,
|
||||
"lines": 95,
|
||||
"statements": 95
|
||||
}
|
||||
},
|
||||
"collectCoverage": true
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
"build": "microbundle --name='svelte-i18n'",
|
||||
"start": "microbundle watch --name='svelte-i18n'",
|
||||
"test": "jest --no-cache --verbose",
|
||||
"test:watch": "jest --no-cache --verbose --watchAll",
|
||||
"lint": "eslint \"*.js\" \"src/**/*.js\"",
|
||||
"format": "prettier --loglevel silent --write \"*.js\" \"src/**/*.js\" && eslint --fix \"*.js\" \"src/**/*.js\"",
|
||||
"prepublishOnly": "npm run format && npm run test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/deepmerge": "^2.1.0",
|
||||
"@types/jest": "^22.0.0",
|
||||
"@types/node": "^10.0.3",
|
||||
"colors": "^1.1.2",
|
||||
"commitizen": "^2.9.6",
|
||||
"coveralls": "^3.0.0",
|
||||
"cross-env": "^5.0.1",
|
||||
"cz-conventional-changelog": "^2.0.0",
|
||||
"husky": "^0.14.0",
|
||||
"jest": "^22.0.2",
|
||||
"lint-staged": "^7.1.3",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"prettier": "^1.13.4",
|
||||
"prompt": "^1.0.0",
|
||||
"replace-in-file": "^3.0.0-beta.2",
|
||||
"rimraf": "^2.6.1",
|
||||
"rollup": "^0.59.2",
|
||||
"rollup-plugin-commonjs": "^9.0.0",
|
||||
"rollup-plugin-json": "^3.0.0",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"rollup-plugin-sourcemaps": "^0.4.2",
|
||||
"rollup-plugin-typescript2": "^0.11.1",
|
||||
"semantic-release": "^15.0.0",
|
||||
"svelte": "^2.9.7",
|
||||
"ts-jest": "^22.0.0",
|
||||
"ts-node": "^6.0.0",
|
||||
"tslint": "^5.8.0",
|
||||
"tslint-config-prettier": "^1.1.0",
|
||||
"tslint-config-standard": "^7.0.0",
|
||||
"typedoc": "^0.11.0",
|
||||
"typescript": "^2.6.2",
|
||||
"validate-commit-msg": "^2.12.2"
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
"eslint-plugin-import": "^2.11.0",
|
||||
"eslint-plugin-node": "^6.0.1",
|
||||
"eslint-plugin-prettier": "^2.6.0",
|
||||
"eslint-plugin-promise": "^3.7.0",
|
||||
"eslint-plugin-standard": "^3.1.0",
|
||||
"jest": "^22.4.3",
|
||||
"microbundle": "^0.4.4",
|
||||
"prettier": "^1.12.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": "^2.1.1",
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import resolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import sourceMaps from 'rollup-plugin-sourcemaps'
|
||||
import camelCase from 'lodash.camelcase'
|
||||
import typescript from 'rollup-plugin-typescript2'
|
||||
import json from 'rollup-plugin-json'
|
||||
|
||||
const pkg = require('./package.json')
|
||||
|
||||
const libraryName = 'svelte-i18n'
|
||||
|
||||
export default {
|
||||
input: `src/${libraryName}.ts`,
|
||||
output: [
|
||||
{ file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true },
|
||||
{ file: pkg.module, format: 'es', sourcemap: true },
|
||||
],
|
||||
// Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash')
|
||||
external: [],
|
||||
watch: {
|
||||
include: 'src/**',
|
||||
},
|
||||
plugins: [
|
||||
// Allow json resolution
|
||||
json(),
|
||||
// Compile TypeScript files
|
||||
typescript({ useTsconfigDeclarationDir: true }),
|
||||
// Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
|
||||
commonjs(),
|
||||
// Allow node_modules resolution, so you can use 'external' to control
|
||||
// which external modules to include in the bundle
|
||||
// https://github.com/rollup/rollup-plugin-node-resolve#usage
|
||||
resolve(),
|
||||
|
||||
// Resolve source maps to the original source
|
||||
sourceMaps(),
|
||||
],
|
||||
}
|
|
@ -4,27 +4,20 @@
|
|||
**/
|
||||
import { isObject, warn } from './utils'
|
||||
|
||||
const RE_TOKEN_LIST_VALUE: RegExp = /^(\d)+/
|
||||
const RE_TOKEN_NAMED_VALUE: RegExp = /^(\w)+/
|
||||
|
||||
type Token = {
|
||||
type: 'text' | 'named' | 'list' | 'unknown'
|
||||
value: string
|
||||
}
|
||||
const RE_TOKEN_LIST_VALUE = /^(\d)+/
|
||||
const RE_TOKEN_NAMED_VALUE = /^(\w)+/
|
||||
|
||||
export default class Formatter {
|
||||
_caches: { [key: string]: Array<Token> }
|
||||
|
||||
constructor() {
|
||||
this._caches = Object.create(null)
|
||||
}
|
||||
|
||||
interpolate(message: string, values: any): Array<any> {
|
||||
interpolate(message, values) {
|
||||
if (!values) {
|
||||
return [message]
|
||||
}
|
||||
|
||||
let tokens: Array<Token> = this._caches[message]
|
||||
let tokens = this._caches[message]
|
||||
if (!tokens) {
|
||||
tokens = parse(message)
|
||||
this._caches[message] = tokens
|
||||
|
@ -35,13 +28,13 @@ export default class Formatter {
|
|||
}
|
||||
|
||||
/** Parse a identification string into cached Tokens */
|
||||
export function parse(format: string): Array<Token> {
|
||||
const tokens: Array<Token> = []
|
||||
let position: number = 0
|
||||
let currentText: string = ''
|
||||
export function parse(format){
|
||||
const tokens = []
|
||||
let position = 0
|
||||
let currentText = ''
|
||||
|
||||
while (position < format.length) {
|
||||
let char: string = format[position++]
|
||||
let char = format[position++]
|
||||
|
||||
/** If found any character that's not a '{' (does not include '\{'), assume text */
|
||||
if (char !== '{' || (position > 0 && char[position - 1] === '\\')) {
|
||||
|
@ -56,7 +49,7 @@ export function parse(format: string): Array<Token> {
|
|||
currentText = ''
|
||||
|
||||
/** Key name */
|
||||
let namedKey: string = ''
|
||||
let namedKey = ''
|
||||
char = format[position++]
|
||||
|
||||
while (char !== '}') {
|
||||
|
@ -82,18 +75,18 @@ export function parse(format: string): Array<Token> {
|
|||
return tokens
|
||||
}
|
||||
|
||||
export function compile(tokens: Array<Token>, values: { [id: string]: any }): Array<any> {
|
||||
const compiled: Array<any> = []
|
||||
let index: number = 0
|
||||
export function compile(tokens, values) {
|
||||
const compiled = []
|
||||
let index = 0
|
||||
|
||||
const mode: string = Array.isArray(values) ? 'list' : isObject(values) ? 'named' : 'unknown'
|
||||
const mode = Array.isArray(values) ? 'list' : isObject(values) ? 'named' : 'unknown'
|
||||
|
||||
if (mode === 'unknown') {
|
||||
return compiled
|
||||
}
|
||||
|
||||
while (index < tokens.length) {
|
||||
const token: Token = tokens[index++]
|
||||
const token = tokens[index++]
|
||||
switch (token.type) {
|
||||
case 'text':
|
||||
compiled.push(token.value)
|
|
@ -0,0 +1,56 @@
|
|||
import deepmerge from 'deepmerge'
|
||||
import resolvePath from 'object-resolve-path'
|
||||
|
||||
import Formatter from './formatter'
|
||||
|
||||
export function i18n(store, localesList) {
|
||||
const formatter = new Formatter()
|
||||
const locales = deepmerge.all(localesList)
|
||||
let currentLocale: string
|
||||
|
||||
const plural = (
|
||||
path,
|
||||
counter,
|
||||
interpolations,
|
||||
locale = currentLocale
|
||||
) => {
|
||||
let message = resolvePath(locales[locale], path)
|
||||
|
||||
if (!message) return path
|
||||
|
||||
const choice = Math.min(Math.abs(counter), 2)
|
||||
message = message.split('|')[choice]
|
||||
|
||||
if (!message) return path
|
||||
|
||||
message = formatter.interpolate(message, interpolations).join('')
|
||||
|
||||
return message.trim()
|
||||
}
|
||||
|
||||
const changeLocale = (newLocale) => {
|
||||
currentLocale = newLocale
|
||||
const _ = (
|
||||
function(path, interpolations, locale = currentLocale) {
|
||||
let message = resolvePath(locales[locale], path)
|
||||
|
||||
if (!message) return path
|
||||
|
||||
message = formatter.interpolate(message, interpolations).join('')
|
||||
|
||||
return message
|
||||
}
|
||||
)
|
||||
|
||||
_.plural = plural
|
||||
|
||||
store.set({ locale: newLocale, _ })
|
||||
}
|
||||
|
||||
store.setLocale = (locale) => store.fire('locale', locale)
|
||||
store.on('locale', changeLocale)
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
export { capital, title, upper, lower } from './utils'
|
|
@ -1,30 +0,0 @@
|
|||
export type InterpolationObj = Array<any> | Object
|
||||
|
||||
export interface TranslationGetter {
|
||||
(str: string, values: Array<String | Number> | Object): string
|
||||
}
|
||||
|
||||
export interface Sveltei18n {
|
||||
(str: string, values: Array<String | Number> | Object): string
|
||||
capitalize: TranslationGetter
|
||||
titlelize: TranslationGetter
|
||||
upper: TranslationGetter
|
||||
lower: TranslationGetter
|
||||
}
|
||||
export interface SvelteEventListener {
|
||||
cancel(): void
|
||||
}
|
||||
|
||||
export interface SvelteStore {
|
||||
on: (event: string, callback: Function) => SvelteEventListener
|
||||
set: (newState: Object) => void
|
||||
fire: (event: string, value: any) => void
|
||||
[prop: string]: any
|
||||
}
|
||||
|
||||
export interface LocaleDictionary {
|
||||
[id: string]: string | Array<string> | LocaleDictionary
|
||||
}
|
||||
export interface Locales {
|
||||
[locale: string]: LocaleDictionary
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import deepmerge from 'deepmerge'
|
||||
import resolvePath from 'object-resolve-path'
|
||||
|
||||
import { InterpolationObj, Sveltei18n, SvelteStore, LocaleDictionary, Locales } from './interfaces'
|
||||
import { capitalize, titlelize, upper, lower } from './utils'
|
||||
import Formatter from './formatter'
|
||||
|
||||
export default function(store: SvelteStore, localesList: Array<Locales>) {
|
||||
const formatter = new Formatter()
|
||||
const locales: Locales = deepmerge.all(localesList)
|
||||
|
||||
store.setLocale = (locale: string) => store.fire('locale', locale)
|
||||
store.on('locale', function(locale: string) {
|
||||
const localeDict: LocaleDictionary = locales[locale]
|
||||
const _ = <Sveltei18n>function(id, values) {
|
||||
let message = resolvePath(localeDict, id) || id
|
||||
message = formatter.interpolate(message, values).join('')
|
||||
return message
|
||||
}
|
||||
|
||||
_.capitalize = (id, values) => capitalize(_(id, values))
|
||||
_.titlelize = (id, values) => titlelize(_(id, values))
|
||||
_.upper = (id, values) => upper(_(id, values))
|
||||
_.lower = (id, values) => lower(_(id, values))
|
||||
|
||||
store.set({ locale, _ })
|
||||
})
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
export const capital = (str) => str.replace(/(^|\s)\S/, l => l.toUpperCase())
|
||||
export const title = (str) => str.replace(/(^|\s)\S/g, l => l.toUpperCase())
|
||||
export const upper = (str) => str.toLocaleUpperCase()
|
||||
export const lower = (str) => str.toLocaleLowerCase()
|
||||
|
||||
export const isObject = (obj) => obj !== null && typeof obj === 'object'
|
||||
|
||||
export function warn(msg, err) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn(`[svelte-i18n] ${msg}`)
|
||||
if (err) {
|
||||
console.warn(err.stack)
|
||||
}
|
||||
}
|
||||
}
|
15
src/utils.ts
15
src/utils.ts
|
@ -1,15 +0,0 @@
|
|||
export const capitalize = (str: string) => str.replace(/(^|\s)\S/, l => l.toUpperCase())
|
||||
export const titlelize = (str: string) => str.replace(/(^|\s)\S/g, l => l.toUpperCase())
|
||||
export const upper = (str: string) => str.toLocaleUpperCase()
|
||||
export const lower = (str: string) => str.toLocaleLowerCase()
|
||||
|
||||
export const isObject = (obj: any) => obj !== null && typeof obj === 'object'
|
||||
|
||||
export function warn(msg: string, err?: Error): void {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn(`[svelte-i18n] ${msg}`)
|
||||
if (err) {
|
||||
console.warn(err.stack)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import i18n from '../src/svelte-i18n'
|
||||
import { i18n } from '../src/svelte-i18n'
|
||||
import { Store } from 'svelte/store.umd'
|
||||
import { capitalize, titlelize, upper, lower, isObject } from '../src/utils'
|
||||
import { capital, title, upper, lower, isObject } from '../src/utils'
|
||||
|
||||
const store = new Store()
|
||||
const locales = {
|
||||
|
@ -8,6 +8,7 @@ const locales = {
|
|||
test: 'teste',
|
||||
phrase: 'adoro banana',
|
||||
phrases: ['Frase 1', 'Frase 2'],
|
||||
pluralization: 'Zero | Um | Muito!',
|
||||
interpolation: {
|
||||
key: 'Olá, {0}! Como está {1}?',
|
||||
named: 'Olá, {name}! Como está {time}?'
|
||||
|
@ -117,34 +118,46 @@ describe('Localization', () => {
|
|||
})
|
||||
).toBe('Olá, Chris! Como está o dia?')
|
||||
})
|
||||
|
||||
it('should handle pluralization with _.plural()', () => {
|
||||
store.setLocale('pt-br')
|
||||
const { locale, _ } = store.get()
|
||||
|
||||
expect(_.plural('pluralization', 0)).toBe('Zero')
|
||||
expect(_.plural('pluralization', 1)).toBe('Um')
|
||||
expect(_.plural('pluralization', -1)).toBe('Um')
|
||||
expect(_.plural('pluralization', -1000)).toBe('Muito!')
|
||||
expect(_.plural('pluralization', 2)).toBe('Muito!')
|
||||
expect(_.plural('pluralization', 100)).toBe('Muito!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Localization utilities', () => {
|
||||
it('should capitalize a translated message', () => {
|
||||
it('should capital a translated message', () => {
|
||||
store.setLocale('pt-br')
|
||||
const { _ } = store.get()
|
||||
|
||||
expect(_.capitalize('phrase')).toBe('Adoro banana')
|
||||
expect(capital(_('phrase'))).toBe('Adoro banana')
|
||||
})
|
||||
|
||||
it('should titlelize a translated message', () => {
|
||||
it('should title a translated message', () => {
|
||||
store.setLocale('pt-br')
|
||||
const { _ } = store.get()
|
||||
|
||||
expect(_.titlelize('phrase')).toBe('Adoro Banana')
|
||||
expect(title(_('phrase'))).toBe('Adoro Banana')
|
||||
})
|
||||
|
||||
it('should lowercase a translated message', () => {
|
||||
store.setLocale('pt-br')
|
||||
const { _ } = store.get()
|
||||
|
||||
expect(_.lower('phrase')).toBe('adoro banana')
|
||||
expect(lower(_('phrase'))).toBe('adoro banana')
|
||||
})
|
||||
|
||||
it('should uppercase a translated message', () => {
|
||||
store.setLocale('pt-br')
|
||||
const { _ } = store.get()
|
||||
|
||||
expect(_.upper('phrase')).toBe('ADORO BANANA')
|
||||
expect(upper(_('phrase'))).toBe('ADORO BANANA')
|
||||
})
|
||||
})
|
|
@ -1,31 +0,0 @@
|
|||
const { cd, exec, echo, touch } = require("shelljs")
|
||||
const { readFileSync } = require("fs")
|
||||
const url = require("url")
|
||||
|
||||
let repoUrl
|
||||
let pkg = JSON.parse(readFileSync("package.json") as any)
|
||||
if (typeof pkg.repository === "object") {
|
||||
if (!pkg.repository.hasOwnProperty("url")) {
|
||||
throw new Error("URL does not exist in repository section")
|
||||
}
|
||||
repoUrl = pkg.repository.url
|
||||
} else {
|
||||
repoUrl = pkg.repository
|
||||
}
|
||||
|
||||
let parsedUrl = url.parse(repoUrl)
|
||||
let repository = (parsedUrl.host || "") + (parsedUrl.path || "")
|
||||
let ghToken = process.env.GH_TOKEN
|
||||
|
||||
echo("Deploying docs!!!")
|
||||
cd("docs")
|
||||
touch(".nojekyll")
|
||||
exec("git init")
|
||||
exec("git add .")
|
||||
exec('git config user.name "Christian Kaisermann"')
|
||||
exec('git config user.email "christian@kaisermann.me"')
|
||||
exec('git commit -m "docs(docs): update gh-pages"')
|
||||
exec(
|
||||
`git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages`
|
||||
)
|
||||
echo("Docs deployed!!")
|
|
@ -1,54 +0,0 @@
|
|||
const path = require("path")
|
||||
const { fork } = require("child_process")
|
||||
const colors = require("colors")
|
||||
|
||||
const { readFileSync, writeFileSync } = require("fs")
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(path.resolve(__dirname, "..", "package.json"))
|
||||
)
|
||||
|
||||
pkg.scripts.prepush = "npm run test:prod && npm run build"
|
||||
pkg.scripts.commitmsg = "validate-commit-msg"
|
||||
|
||||
writeFileSync(
|
||||
path.resolve(__dirname, "..", "package.json"),
|
||||
JSON.stringify(pkg, null, 2)
|
||||
)
|
||||
|
||||
// Call husky to set up the hooks
|
||||
fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install"))
|
||||
|
||||
console.log()
|
||||
console.log(colors.green("Done!!"))
|
||||
console.log()
|
||||
|
||||
if (pkg.repository.url.trim()) {
|
||||
console.log(colors.cyan("Now run:"))
|
||||
console.log(colors.cyan(" npm install -g semantic-release-cli"))
|
||||
console.log(colors.cyan(" semantic-release-cli setup"))
|
||||
console.log()
|
||||
console.log(
|
||||
colors.cyan('Important! Answer NO to "Generate travis.yml" question')
|
||||
)
|
||||
console.log()
|
||||
console.log(
|
||||
colors.gray(
|
||||
'Note: Make sure "repository.url" in your package.json is correct before'
|
||||
)
|
||||
)
|
||||
} else {
|
||||
console.log(
|
||||
colors.red(
|
||||
'First you need to set the "repository.url" property in package.json'
|
||||
)
|
||||
)
|
||||
console.log(colors.cyan("Then run:"))
|
||||
console.log(colors.cyan(" npm install -g semantic-release-cli"))
|
||||
console.log(colors.cyan(" semantic-release-cli setup"))
|
||||
console.log()
|
||||
console.log(
|
||||
colors.cyan('Important! Answer NO to "Generate travis.yml" question')
|
||||
)
|
||||
}
|
||||
|
||||
console.log()
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"module":"es2015",
|
||||
"lib": ["es2015", "es2016", "es2017", "dom"],
|
||||
"strict": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"declarationDir": "dist/types",
|
||||
"outDir": "dist/lib",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"extends": [
|
||||
"tslint-config-standard",
|
||||
"tslint-config-prettier"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue