Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MESDK-77 Requirements for Gender and Plurals [WORKING DRAFT] #2655

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7b8df46
Set up ICU2 Plugin
LorisSigrist Apr 25, 2024
c3abc51
Update message interface
LorisSigrist Apr 25, 2024
8aaf0eb
Make "text" lowercase for AST compatibility
LorisSigrist Apr 25, 2024
209754a
Start Parsing Messages
LorisSigrist Apr 25, 2024
cf586fa
Make the ICU Import plugin work
LorisSigrist Apr 25, 2024
5eafaeb
Shuffle some stuff around
LorisSigrist Apr 25, 2024
d2f423f
Make it work
LorisSigrist Apr 25, 2024
c775ad0
Add tests
LorisSigrist Apr 25, 2024
8b57ed5
Merge branch 'main' into lorissigrist/mesdk-77-requirements-for-gende…
LorisSigrist Apr 25, 2024
641a666
Merge remote-tracking branch 'origin/main' into lorissigrist/mesdk-77…
LorisSigrist Apr 26, 2024
d140a41
Make SDK Build and add test project
LorisSigrist Apr 26, 2024
195cb66
Merge branch 'main' into lorissigrist/mesdk-77-requirements-for-gende…
LorisSigrist Apr 29, 2024
53d191c
Add more examples
LorisSigrist Apr 29, 2024
254885d
Multiple languages
LorisSigrist Apr 29, 2024
250ab0d
Have LegacyMessage and the new MessageBundles side by side
LorisSigrist Apr 29, 2024
bdfc77b
Add AST to SDK
LorisSigrist Apr 29, 2024
ded750b
Continue on conversion functions
LorisSigrist Apr 29, 2024
67fa197
Make conversion work
LorisSigrist Apr 29, 2024
45e12a8
Get SDK to build
LorisSigrist Apr 29, 2024
1361784
Add Importer Module Type
LorisSigrist Apr 29, 2024
cead1c4
Get started on Importer Type
LorisSigrist Apr 29, 2024
908d22f
Implement first Importer
LorisSigrist Apr 29, 2024
be00a86
Resolve Importers
LorisSigrist Apr 29, 2024
9be7eef
fixes circular dependency
martin-lysk Apr 30, 2024
129591a
adds old normalizeMessage function again
martin-lysk May 2, 2024
3140549
WIP: Fixes all tests but @inlang/icu2-message-format-test:test - foll…
martin-lysk May 2, 2024
17521d5
Merge branch 'main' into lorissigrist/mesdk-77-requirements-for-gende…
jldec May 2, 2024
d1879fd
revert changed multi-project-test file
jldec May 2, 2024
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
5 changes: 5 additions & 0 deletions .changeset/poor-trains-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inlang/message": major
---

Support valid ICU MessageFormat 2.0 Messages
28 changes: 28 additions & 0 deletions inlang/development-projects/icu2/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { loadProject } from "@inlang/sdk"
import { openRepository } from "@lix-js/client"
import nodeishFs from "node:fs/promises"
import path from "node:path"

const projectPath = path.join(process.cwd(), "project.inlang")

const repo = await openRepository("file://" + process.cwd(), {
nodeishFs,
})

const project = await loadProject({
projectPath,
repo,
})
const errors = project.errors()

if (errors) {
console.error(errors)
process.exit(1)
}

await sleep(500)
const messages = project.query.messages((newMessages) => console.log(newMessages))

async function sleep(ms) {
return await new Promise((resolve) => setTimeout(resolve, ms))
}
1 change: 1 addition & 0 deletions inlang/development-projects/icu2/messages/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
6 changes: 6 additions & 0 deletions inlang/development-projects/icu2/messages/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"input-local-match": ".input {$var :number maximumFractionDigits=0}\n.local $rounded={$var :number maximumFractionDigits=2}\n.match {$rounded} 0 {{The selector can apply a different annotation to {$var} for the purposes of selection}} * {{A placeholder in a pattern can apply a different annotation to {$var :number maximumFractionDigits=3}}}",
"chained_locals": ".input {$number}\n.local $clamped={$number :clamp min=0}\n.local $price={$clamped :curreny currency=EUR}\n.match {$clamped} 0 {{Free}} * {{Price: {$price}}}",
"many_cases": ".match {$numLikes :number} {$numShares :number} \n0 0 {{Your item has no likes and has not been shared.}}\n0 one {{Your item has no likes and has been shared {$numShares} time.}}\n0 * {{Your item has no likes and has been shared {$numShares} times.}}\none 0 {{Your item has {$numLikes} like and has not been shared.}}\none one {{Your item has {$numLikes} like and has been shared {$numShares} time.}}\none * {{Your item has {$numLikes} like and has been shared {$numShares} times.}}\n* 0 {{Your item has {$numLikes} likes and has not been shared.}}\n* one {{Your item has {$numLikes} likes and has been shared {$numShares} time.}}\n* * {{Your item has {$numLikes} likes and has been shared {$numShares} times.}}",
"basic_function": "hello {-4.20 :integer}"
}
11 changes: 11 additions & 0 deletions inlang/development-projects/icu2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@inlang/icu2-message-format-test",
"type": "module",
"scripts": {
"test": "node ./main.js"
},
"dependencies": {
"@inlang/sdk": "workspace:*",
"@lix-js/client": "workspace:*"
}
}
1 change: 1 addition & 0 deletions inlang/development-projects/icu2/project.inlang/project_id
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9172fdc9c173f37e82af2cdb061c10c702b76298ccef49949d87db06649d7f5b
12 changes: 12 additions & 0 deletions inlang/development-projects/icu2/project.inlang/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://inlang.com/schema/project-settings",
"sourceLanguageTag": "en",
"languageTags": ["en", "de"],
"modules": ["./../../source-code/importers/icu2-message-format/dist/index.js"],
"importer.inlang.icu2MessageFormat": {
"pathPattern": "./messages/{languageTag}.json"
},
"experimental": {
"aliases": true
}
}
21 changes: 21 additions & 0 deletions inlang/source-code/importers/icu2-message-format/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Inlang

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions inlang/source-code/importers/icu2-message-format/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# An Experimental Importer for the ICU Message Format 2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"$schema": "https://inlang.com/schema/marketplace-manifest",
"id": "importer.inlang.icu2MessageFormat",
"displayName": {
"en": "ICU MessageFormat 2.0"
},
"description": {
"en": "Don't use this"
},
"pages": {
"/": "./inlang/source-code/plugins/icu2-message-format/README.md",
"/changelog": "./inlang/source-code/plugins/icu2--message-format/CHANGELOG.md"
},
"keywords": [
"website",
"svelte",
"react",
"nextjs",
"vue",
"javascript",
"storage",
"save",
"load",
"import",
"export",
"messages",
"plugin",
"solid",
"astro"
],
"recommends": ["m/tdozzpar", "m/2qj2w8pu", "m/r7kp499g", "m/gerre34r"],
"publisherName": "inlang",
"publisherIcon": "https://inlang.com/favicon/safari-pinned-tab.svg",
"license": "Apache-2.0",
"module": "https://cdn.jsdelivr.net/npm/@inlang/icu2-message-format@latest/dist/index.js"
}
32 changes: 32 additions & 0 deletions inlang/source-code/importers/icu2-message-format/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@inlang/icu2-message-format",
"version": "0.0.1",
"type": "module",
"exports": {
"./storage-schema": "./src/storageSchema.ts"
},
"files": [
"./dist"
],
"private": true,
"scripts": {
"dev": "inlang module build --entry ./src/index.ts --outdir ./dist --watch",
"build": "inlang module build --entry ./src/index.ts --outdir ./dist",
"test": "vitest run",
"lint": "eslint ./src --fix",
"format": "prettier ./src --write",
"clean": "rm -rf ./dist ./node_modules"
},
"devDependencies": {
"@inlang/cli": "workspace:*",
"@inlang/detect-json-formatting": "workspace:*",
"@inlang/message": "workspace:*",
"@sinclair/typebox": "^0.31.17",
"@vitest/coverage-v8": "^0.33.0",
"typescript": "^5.1.3",
"vitest": "0.33.0"
},
"dependencies": {
"messageformat": "4.0.0-7"
}
}
2 changes: 2 additions & 0 deletions inlang/source-code/importers/icu2-message-format/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { plugin } from "./plugin.js"
export default plugin
145 changes: 145 additions & 0 deletions inlang/source-code/importers/icu2-message-format/src/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { describe, it, expect } from "vitest"
import { parseICUMessage } from "./plugin"
import { Translation } from "@inlang/sdk"

describe("parseICUMessage", () => {
describe("simple message", () => {
it("should parse a simple text-only message", () => {
const message = parseICUMessage("en", "Hello World")
const expected: Translation = {
declarations: [],
selectors: [],
languageTag: "en",
variants: [
{
match: [],
pattern: [
{
type: "text",
value: "Hello World",
},
],
},
],
}
expect(message).toEqual(expected)
})
})

describe("select message", () => {
it("parses a message with an annotation in the input and the selector", () => {
// MUST NOT INCLUDE WHITESPACE BEFORE OR AFTER THE MESSAGE
const source = `.input {$var :number maximumFractionDigits=0}
.match {$var :number maximumFractionDigits=2}
0 {{The selector can apply a different annotation to {$var} for the purposes of selection}}
* {{A placeholder in a pattern can apply a different annotation to {$var :number maximumFractionDigits=3}}}`
const message = parseICUMessage("de", source)

const expected: Translation = {
languageTag: "de",
declarations: [
{
type: "input",
name: "var",
value: {
type: "expression",
arg: {
type: "variable",
name: "var",
},

annotation: {
type: "function",
name: "number",
options: [
{
name: "maximumFractionDigits",
value: {
type: "literal",
value: "0",
},
},
],
},
},
},
],
selectors: [
{
type: "expression",
arg: {
type: "variable",
name: "var",
},
annotation: {
type: "function",
name: "number",
options: [
{
name: "maximumFractionDigits",
value: {
type: "literal",
value: "2",
},
},
],
},
},
],
variants: [
{
match: ["0"],
pattern: [
{
type: "text",
value: "The selector can apply a different annotation to ",
},
{
type: "expression",
arg: {
type: "variable",
name: "var",
},
},
{
type: "text",
value: " for the purposes of selection",
},
],
},
{
match: ["*"],
pattern: [
{
type: "text",
value: "A placeholder in a pattern can apply a different annotation to ",
},
{
type: "expression",
arg: {
type: "variable",
name: "var",
},
annotation: {
type: "function",
name: "number",
options: [
{
name: "maximumFractionDigits",
value: {
type: "literal",
value: "3",
},
},
],
},
},
],
},
],
}

expect(message).toEqual(expected)
})
})
})
Loading
Loading