Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bobril-g11n

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bobril-g11n - npm Package Compare versions

Comparing version 4.4.1 to 5.0.0

14

CHANGELOG.md
# CHANGELOG
## 5.0.0
Needs TypeScript 3.7+, directly depends on Bobril. Support formatting of elements of virtual dom.
```tsx
f("Hello {1}{world}{/1}", { 1: (p: b.IBobrilChildren) => <b>{p}</b>, world: "World" });
f("Simple {1/}", { 1: () => <App /> });
// Next thing also needs support in bobril-build
<T hint="translation hint" param1={42}>
Answer is <strong>{t("{param1}")}</strong>!
</T>;
```
## 4.4.1

@@ -4,0 +18,0 @@

0

index.ts

@@ -0,0 +0,0 @@ export * from './src/msgFormatParser';

4

package.json
{
"name": "bobril-g11n",
"version": "4.4.1",
"version": "5.0.0",
"description": "Bobril globalization",

@@ -10,6 +10,6 @@ "main": "index.js",

"dependencies": {
"bobril": "*",
"moment": "^2.10.6"
},
"devDependencies": {
"bobril": "*",
"typescript": "*"

@@ -16,0 +16,0 @@ },

@@ -0,0 +0,0 @@ # bobril-g11n

@@ -0,15 +1,18 @@

import { MsgAst } from "./msgFormatParser";
import { isString, isArray } from "bobril";
export function extractUsedParams(msgAst: any): string[] {
let params = Object.create(null);
extractUsedParamsRec(params, msgAst);
let params = Object.create(null);
extractUsedParamsRec(params, msgAst);
return Object.keys(params).sort();
}
function extractUsedParamsRec(usedParams: { [name:string]:boolean }, msgAst: any) {
if (typeof msgAst === 'string') {
function extractUsedParamsRec(usedParams: { [name: string]: boolean }, msgAst: MsgAst) {
if (isString(msgAst)) {
return;
}
if (Array.isArray(msgAst)) {
if (isArray(msgAst)) {
for (let i = 0; i < msgAst.length; i++) {
let item = msgAst[i];
extractUsedParamsRec(usedParams, item);
extractUsedParamsRec(usedParams, item);
}

@@ -19,35 +22,40 @@ return;

switch (msgAst.type) {
case 'arg':
usedParams[msgAst.id] = true;
case "arg":
usedParams[msgAst.id] = true;
return;
case 'hash':
return;
case 'format':
usedParams[msgAst.id] = true;
case "hash":
return;
case "concat":
extractUsedParamsRec(usedParams, msgAst.values);
return;
case "el":
usedParams[msgAst.id] = true;
if (msgAst.value != undefined) extractUsedParamsRec(usedParams, msgAst.value);
return;
case "format":
usedParams[msgAst.id] = true;
let type = msgAst.format.type;
switch (type) {
case 'plural':
case 'select':
{
let options = msgAst.format.options;
case "plural":
case "select": {
let options = msgAst.format.options;
for (let i = 0; i < options.length; i++) {
let opt = options[i];
extractUsedParamsRec(usedParams, opt.value);
}
break;
}
case "number":
case "date":
case "time": {
let options = msgAst.format.options;
if (options) {
for (let i = 0; i < options.length; i++) {
let opt = options[i];
extractUsedParamsRec(usedParams, opt.value);
if (typeof options[i].value === "object") {
extractUsedParamsRec(usedParams, options[i].value);
}
}
break;
}
case 'number':
case 'date':
case 'time':
{
//let style = msgAst.format.style || 'default';
let options = msgAst.format.options;
if (options) {
for (let i = 0; i < options.length; i++) {
if (typeof options[i].value === 'object') {
extractUsedParamsRec(usedParams, options[i].value);
}
}
}
}
break;
}
}

@@ -54,0 +62,0 @@ return;

@@ -0,0 +0,0 @@ export interface ILocaleRules {

@@ -0,1 +1,17 @@

import { isObject, isArray } from "bobril";
type MsgAstError = { type: "error"; msg: string; pos: number; line: number; col: number };
export type MsgAst =
| MsgAstError
| string
| Array<MsgAst>
| { type: "hash" }
| { type: "arg"; id: string }
| { type: "el"; id: number; value?: MsgAst }
| { type: "format"; id: string; format: Record<string, any> }
| { type: "concat"; values: Array<MsgAst> };
type MsgAstInternal = MsgAst | { type: "open"; id: number } | { type: "close"; id: number };
let sourceText: string;

@@ -9,3 +25,3 @@ let pos: number;

let curToken: number;
let errorMsg: string;
let errorMsg: string | undefined;

@@ -18,3 +34,3 @@ const EOFToken = -1;

function advanceNextToken() {
function advanceNextToken(): void {
curLine = nextLine;

@@ -28,3 +44,4 @@ curCol = nextCol;

if (ch === 13 || ch === 10) {
nextLine++; nextCol = 1;
nextLine++;
nextCol = 1;
if (ch === 13 && pos < length && sourceText.charCodeAt(pos) === 10) {

@@ -37,3 +54,4 @@ pos++;

nextCol++;
if (ch === 92) { // \
if (ch === 92) {
// \
if (pos === length) {

@@ -45,10 +63,12 @@ curToken = 92;

nextCol++;
if (ch === 92 || ch === 123 || ch === 125 || ch === 35) { // \ { } #
if (ch === 92 || ch === 123 || ch === 125 || ch === 35) {
// \ { } #
curToken = ch;
return;
}
if (ch === 117) { // u
if (ch === 117) {
// u
if (pos + 4 <= length) {
let hexcode = sourceText.substr(pos, 4);
if (/^[0-9a-f]+$/ig.test(hexcode)) {
if (/^[0-9a-f]+$/gi.test(hexcode)) {
curToken = parseInt(hexcode, 16);

@@ -60,15 +80,18 @@ pos += 4;

}
errorMsg = 'After \\u there must be 4 hex characters';
errorMsg = "After \\u there must be 4 hex characters";
curToken = ErrorToken;
return;
}
errorMsg = 'After \\ there coud be only one of \\{}#u characters';
errorMsg = "After \\ there coud be only one of \\{}#u characters";
curToken = ErrorToken;
return;
}
if (ch === 123) { // {
if (ch === 123) {
// {
curToken = OpenBracketToken;
} else if (ch === 125) { // }
} else if (ch === 125) {
// }
curToken = CloseBracketToken;
} else if (ch === 35) { // #
} else if (ch === 35) {
// #
curToken = HashToken;

@@ -80,9 +103,9 @@ } else {

function isError(val: any): boolean {
return (val != null && typeof val === 'object' && val.type === 'error');
export function isParserError(val: MsgAst): val is MsgAstError {
return isObject(val) && !isArray(val) && val.type === "error";
}
function buildError(msg?: string): any {
if (msg === undefined) msg = errorMsg;
return { type: 'error', msg, pos: pos - 1, line: curLine, col: curCol };
function buildError(msg?: string): MsgAstError {
if (msg === undefined) msg = errorMsg || "Error";
return { type: "error", msg, pos: pos - 1, line: curLine, col: curCol };
}

@@ -96,12 +119,22 @@

function parseIdentificator(): any {
let identificator = '';
if (curToken >= 65 && curToken <= 90 || curToken >= 97 && curToken <= 122 || curToken === 95) {
function parseIdentificator(): string | MsgAstError {
let identificator = "";
if ((curToken >= 65 && curToken <= 90) || (curToken >= 97 && curToken <= 122) || curToken === 95) {
do {
identificator += String.fromCharCode(curToken);
advanceNextToken();
} while (curToken >= 65 && curToken <= 90 || curToken >= 97 && curToken <= 122 || curToken === 95 || curToken >= 48 && curToken <= 57);
} else {
return buildError('Expecting identifier [a-zA-Z_]');
}
} while (
(curToken >= 65 && curToken <= 90) ||
(curToken >= 97 && curToken <= 122) ||
curToken === 95 ||
(curToken >= 48 && curToken <= 57)
);
} else if (curToken >= 47 && curToken <= 57) {
do {
identificator += String.fromCharCode(curToken);
advanceNextToken();
} while (curToken >= 47 && curToken <= 57);
if (identificator.charCodeAt(0) == 47 && identificator.charCodeAt(identificator.length - 1) == 47)
return buildError("Slash could be only on one side of number");
} else return buildError("Expecting identifier [a-zA-Z_] or number");
return identificator;

@@ -111,3 +144,3 @@ }

function parseChars(): string {
let res = '';
let res = "";
do {

@@ -121,3 +154,3 @@ res += String.fromCharCode(curToken);

function parseNumber(): number {
let number = '';
let number = "";
do {

@@ -143,7 +176,20 @@ number += String.fromCharCode(curToken);

const numClasses: { [name: string]: number } = { zero: 1, one: 1, two: 1, few: 1, many: 1, other: 1 };
function parseFormat(): any {
function parseFormat(): MsgAstInternal {
skipWs();
if (curToken === ErrorToken) return buildError();
let identificator = parseIdentificator();
if (isError(identificator)) return identificator;
if (isParserError(identificator)) return identificator;
if (identificator[0] <= "9") {
if (isCloseBracketToken()) {
advanceNextToken();
if (identificator[identificator.length - 1] == "/") {
return { type: "el", id: parseInt(identificator.substr(0, identificator.length - 1)) };
}
if (identificator[0] == "/") {
return { type: "close", id: parseInt(identificator.substr(1, identificator.length - 1)) };
}
return { type: "open", id: parseInt(identificator) };
}
return buildError("element could not have parameters");
}
skipWs();

@@ -153,5 +199,6 @@ if (curToken === ErrorToken) return buildError();

advanceNextToken();
return { type: 'arg', id: identificator };
return { type: "arg", id: identificator };
}
if (!isComma()) { // ,
if (!isComma()) {
// ,
return buildError('Expecting "}" or ","');

@@ -163,11 +210,11 @@ }

let res = {
type: 'format',
type: "format",
id: identificator,
format
};
} as const;
let name = parseIdentificator();
if (isError(name)) return name;
if (isParserError(name)) return name;
skipWs();
if (curToken === ErrorToken) return buildError();
if (name === 'number' || name === 'time' || name === 'date') {
if (name === "number" || name === "time" || name === "date") {
format.type = name;

@@ -180,7 +227,8 @@ format.style = null;

}
if (isComma()) { // ,
if (isComma()) {
// ,
advanceNextToken();
skipWs();
let style = parseIdentificator();
if (isError(style)) return name;
if (isParserError(style)) return name;
format.style = style;

@@ -195,8 +243,10 @@ format.options = [];

}
if (isComma()) { // ,
if (isComma()) {
// ,
advanceNextToken();
skipWs();
let optionName = parseIdentificator();
if (isError(optionName)) return optionName;
if (curToken === 58) { // :
if (isParserError(optionName)) return optionName;
if (curToken === 58) {
// :
advanceNextToken();

@@ -213,3 +263,3 @@ skipWs();

}
if (isError(val)) return val;
if (isParserError(val)) return val;
format.options.push({ key: optionName, value: val });

@@ -225,9 +275,9 @@ } else {

return buildError('Expecting "," or "}"');
} else if (name === 'plural' || name === 'selectordinal') {
} else if (name === "plural" || name === "selectordinal") {
let options: any[] = [];
format.type = 'plural';
format.ordinal = name !== 'plural';
format.type = "plural";
format.ordinal = name !== "plural";
format.offset = 0;
format.options = options;
if (!isComma()) { // ,
if (!isComma()) {
return buildError('Expecting ","');

@@ -248,6 +298,6 @@ }

format.offset = parseInt(m[1], 10);
} else if (chars === 'offset:') {
} else if (chars === "offset:") {
skipWs();
if (curToken < 48 || curToken > 57) {
return buildError('Expecting number');
return buildError("Expecting number");
}

@@ -265,3 +315,4 @@ format.offset = parseNumber();

selector = chars;
if (!numClasses[selector]) return buildError("Selector " + selector + " is not one of " + Object.keys(numClasses).join(", "));
if (!numClasses[selector])
return buildError("Selector " + selector + " is not one of " + Object.keys(numClasses).join(", "));
}

@@ -273,3 +324,3 @@ if (!isOpenBracketToken()) {

let value = parseMsg(false);
if (isError(value)) return value;
if (isParserError(value)) return value;
options.push({ selector, value });

@@ -280,7 +331,8 @@ skipWs();

return res;
} else if (name === 'select') {
} else if (name === "select") {
let options: any[] = [];
format.type = 'select';
format.type = "select";
format.options = options;
if (!isComma()) { // ,
if (!isComma()) {
// ,
return buildError('Expecting ","');

@@ -307,3 +359,3 @@ }

let value = parseMsg(false);
if (isError(value)) return value;
if (isParserError(value)) return value;
options.push({ selector, value });

@@ -318,4 +370,10 @@ skipWs();

function parseMsg(endWithEOF: boolean): any {
let res: any = null;
function parseMsg(endWithEOF: boolean | number): MsgAst {
let res: MsgAst | null = null;
let wrapByConcat = false;
function normalize(res: MsgAst | null): MsgAst {
if (res === null) return "";
if (!isArray(res) || !wrapByConcat) return res;
return { type: "concat", values: res };
}
while (true) {

@@ -326,24 +384,39 @@ if (curToken === ErrorToken) {

if (curToken === EOFToken) {
if (endWithEOF) {
if (res === null) return '';
return res;
if (endWithEOF === true) {
return normalize(res);
}
return buildError('Unexpected end of message missing "}"');
if (endWithEOF === false) return buildError('Unexpected end of message missing "}"');
return buildError('Unexpected end of message missing "{/' + endWithEOF + '}"');
}
let val: any;
let val: MsgAst;
if (curToken === OpenBracketToken) {
advanceNextToken();
val = parseFormat();
let format = parseFormat();
if (isObject(format) && !isArray(format)) {
if (format.type == "open") {
const nested = parseMsg(format.id);
if (isParserError(nested)) return nested;
format = { type: "el", id: format.id, value: nested };
wrapByConcat = true;
} else if (format.type == "close") {
if (format.id === endWithEOF) {
return normalize(res);
}
return buildError('Missing closing "{/' + endWithEOF + '}" got "{/' + format.id + '}" instead.');
} else if (format.type == "el") {
wrapByConcat = true;
}
}
val = format;
} else if (curToken === HashToken) {
advanceNextToken();
val = { type: 'hash' };
val = { type: "hash" };
} else if (curToken === CloseBracketToken) {
if (endWithEOF) {
if (endWithEOF !== false) {
return buildError('Unexpected "}". Maybe you forgot to prefix it with "\\".');
}
advanceNextToken();
if (res === null) return '';
return res;
return normalize(res);
} else {
val = '';
val = "";
while (curToken >= 0) {

@@ -354,4 +427,5 @@ val += String.fromCharCode(curToken);

}
if (isError(val)) return val;
if (res === null) res = val; else {
if (isParserError(val)) return val;
if (res === null) res = val;
else {
if (Array.isArray(res)) {

@@ -366,3 +440,3 @@ res.push(val);

export function parse(text: string): any {
export function parse(text: string): MsgAst {
pos = 0;

@@ -369,0 +443,0 @@ sourceText = text;

@@ -5,3 +5,5 @@ import * as moment from "moment";

import * as numberFormatter from "./numberFormatter";
import { MsgAst } from "./msgFormatParser";
import { f } from "./translate";
import { isString, isArray } from "bobril";

@@ -120,7 +122,7 @@ (<any>window).moment = moment;

export function compile(locale: string, msgAst: any): (params?: Object, hashArg?: string) => string {
if (typeof msgAst === "string") {
export function compile(locale: string, msgAst: MsgAst): (params?: Object, hashArg?: string) => string {
if (isString(msgAst)) {
return () => msgAst;
}
if (Array.isArray(msgAst)) {
if (isArray(msgAst)) {
if (msgAst.length === 0) return () => "";

@@ -151,2 +153,29 @@ let comp = new RuntimeFunctionGenerator();

};
case "concat": {
const vals = msgAst.values;
if (vals.length === 0) return () => "";
let comp = new RuntimeFunctionGenerator();
let argParams = comp.addArg(0);
let argHash = comp.addArg(1);
comp.addBody("return [");
for (let i = 0; i < vals.length; i++) {
if (i > 0) comp.addBody(",");
let item = vals[i];
if (isString(item)) {
comp.addBody(comp.addConstant(item));
} else {
comp.addBody(comp.addConstant(compile(locale, item)) + `(${argParams},${argHash})`);
}
}
comp.addBody("];");
return <(params?: Object, hashArg?: string) => string>comp.build();
}
case "el":
if (msgAst.value != undefined) {
return ((id: number, valueFactory: (params?: Object, hashArg?: string) => any) => (
params?: Object,
hashArg?: string
) => (<any>params)[id](valueFactory(params, hashArg)))(msgAst.id, compile(locale, msgAst.value));
}
return ((id: number) => (params?: Object) => (<any>params)[id]())(msgAst.id);
case "format":

@@ -153,0 +182,0 @@ let comp = new RuntimeFunctionGenerator();

@@ -0,0 +0,0 @@ import { ILocaleRules } from "./localeDataStorage";

@@ -0,0 +0,0 @@ export class RuntimeFunctionGenerator {

@@ -0,1 +1,2 @@

import * as b from "bobril";
import * as moment from "moment";

@@ -8,7 +9,2 @@ import * as msgFormatParser from "./msgFormatParser";

declare var b: {
setBeforeInit(callback: (cb: () => void) => void): void;
ignoreShouldChange(): void;
};
export interface IG11NConfig {

@@ -95,3 +91,3 @@ defaultLocale?: string;

let ast = msgFormatParser.parse(currentTranslationMessage(message));
if (ast.type === "error") {
if (msgFormatParser.isParserError(ast)) {
throw new Error("message " + message + " in " + currentLocale + " has error: " + ast.msg);

@@ -107,3 +103,3 @@ }

let ast = msgFormatParser.parse(message);
if (ast.type === "error") {
if (msgFormatParser.isParserError(ast)) {
throw new Error('message "' + message + '" has error: ' + ast.msg + " on position: " + ast.pos);

@@ -318,1 +314,5 @@ }

}
export function T(data?: b.IFragmentData | Record<string, any>) {
return data;
}

@@ -6,2 +6,3 @@ {

"declaration": true,
"downlevelIteration": true,
"experimentalDecorators": true,

@@ -15,2 +16,3 @@ "jsx": "react",

"es2015.iterable",
"es2015.generator",
"es2015.collection"

@@ -29,3 +31,3 @@ ],

"removeComments": false,
"skipLibCheck": true,
"skipLibCheck": false,
"skipDefaultLibCheck": true,

@@ -35,7 +37,7 @@ "sourceMap": true,

"strictNullChecks": true,
"target": "es5"
"target": "es5",
"resolveJsonModule": true
},
"files": [
"node_modules/bobril/jsx.d.ts",
"C:/Users/b.letocha/.bbcore/tools/jasmine.d.ts"
"C:/Users/boris/.bbcore/tools/jasmine330.d.ts"
],

@@ -42,0 +44,0 @@ "include": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc