Skip to content

Commit

Permalink
fix generate ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
wmertens committed Mar 22, 2024
1 parent 010d737 commit 1a11b01
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 59 deletions.
4 changes: 2 additions & 2 deletions qwik.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ export const onRequest: RequestHandler = async ({
params.locale === '__' ||
/^([a-z]{2})([_-]([a-z]{2}))?$/i.test(params.locale)
? // invalid locale
'/' + replaceLocale(pathname, params.locale, guessedLocale)
'/' + replaceLocale(pathname, params.locale, guessedLocale)
: // no locale
`/${guessedLocale}${pathname}`
`/${guessedLocale}${pathname}`
throw redirect(301, `${path}${url.search}`)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/interpolate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export const interpolate = (tr: string | Plural, params: unknown[] = []) => {
return tr
? (tr as string).replace(/\$([\d$])/g, (_, i) =>
i === '$' ? '$' : String(params[Number(i) - 1] ?? '')
)
)
: ''
}
12 changes: 6 additions & 6 deletions src/transform-localize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ describe('transform', () => {
pluralKeys: new Set(['plural $1']),
})
).toMatchInlineSnapshot(`
"
import { _, localize as meep, interpolate as __interpolate__ } from 'compiled-i18n';
const Foo = component$<{t: number;}>((p) =>
<div title={__interpolate__(__$LOCALIZE$__(\\"plural $1\\"), t)}>{__$LOCALIZE$__(\\"Hello $1 lol $2\\", t, t + 1)}</div>
);"
`)
"
import { _, localize as meep, interpolate as __interpolate__ } from 'compiled-i18n';
const Foo = component$<{t: number;}>((p) =>
<div title={__interpolate__(__$LOCALIZE$__("plural $1"), t)}>{__$LOCALIZE$__("Hello $1 lol $2", t, t + 1)}</div>
);"
`)
})
test('disallows newlines', () => {
expect(() =>
Expand Down
2 changes: 1 addition & 1 deletion src/transform-localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export const makeTransExpr = (tr: unknown, paramExprs: string[]) => {
// Translator error
if (p == null) return ''
return `\${${p}}`
})}\``
})}\``
}

const marker = '__$LOCALIZE$__('
Expand Down
54 changes: 27 additions & 27 deletions src/vite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test('build', async () => {
) as Rollup.OutputChunk
expect(index).toBeTruthy()
expect.soft(index.code).toMatchInlineSnapshot(`
"const o=\\"world\\";console.log(__$LOCALIZE$__(\\"hello $1\\",o));
"const o="world";console.log(__$LOCALIZE$__("hello $1",o));
"
`)

Expand All @@ -55,7 +55,7 @@ test('build', async () => {
) as Rollup.OutputAsset
expect(testIndex).toBeTruthy()
expect.soft(testIndex.source).toMatchInlineSnapshot(`
"const o=\\"world\\";console.log(\`Hello \${o}!\`);
"const o="world";console.log(\`Hello \${o}!\`);
"
`)
})
Expand All @@ -68,7 +68,7 @@ test('plural', async () => {
) as Rollup.OutputChunk
expect(multi).toBeTruthy()
expect.soft(multi.code).toMatchInlineSnapshot(`
"const n=(e,$=[])=>{if(typeof e==\\"object\\"){let o=e[$[0]]??e[\\"*\\"];typeof o==\\"number\\"&&(o=e[o]),e=o}return e?e.replace(/\\\\$([\\\\d$])/g,(o,l)=>l===\\"$\\"?\\"$\\":String($[Number(l)-1]??\\"\\")):\\"\\"};console.log(__$LOCALIZE$__(\\"hello $1\\",n(__$LOCALIZE$__(\\"worlds $1\\"),1)));
"const n=(e,$=[])=>{if(typeof e=="object"){let o=e[$[0]]??e["*"];typeof o=="number"&&(o=e[o]),e=o}return e?e.replace(/\\$([\\d$])/g,(o,l)=>l==="$"?"$":String($[Number(l)-1]??"")):""};console.log(__$LOCALIZE$__("hello $1",n(__$LOCALIZE$__("worlds $1"),1)));
"
`)

Expand All @@ -77,7 +77,7 @@ test('plural', async () => {
) as Rollup.OutputAsset
expect(enMulti).toBeTruthy()
expect.soft(enMulti.source).toMatchInlineSnapshot(`
"const n=(e,$=[])=>{if(typeof e==\\"object\\"){let o=e[$[0]]??e[\\"*\\"];typeof o==\\"number\\"&&(o=e[o]),e=o}return e?e.replace(/\\\\$([\\\\d$])/g,(o,l)=>l===\\"$\\"?\\"$\\":String($[Number(l)-1]??\\"\\")):\\"\\"};console.log(\`Hello \${n({\\"1\\":\\"world\\",\\"*\\":\\"worlds\\"},1)}!\`);
"const n=(e,$=[])=>{if(typeof e=="object"){let o=e[$[0]]??e["*"];typeof o=="number"&&(o=e[o]),e=o}return e?e.replace(/\\$([\\d$])/g,(o,l)=>l==="$"?"$":String($[Number(l)-1]??"")):""};console.log(\`Hello \${n({"1":"world","*":"worlds"},1)}!\`);
"
`)
})
Expand All @@ -96,7 +96,7 @@ test('noInline', async () => {
expect(index.code).toContain('Test :-)')
expect(index.code).toContain('worlds $1')
expect.soft(index.code).toMatchInlineSnapshot(`
"const s={te_ST:\\"Test :-)\\"};let a=\\"te_ST\\",l,i=()=>{if(l)return l;if(typeof document<\\"u\\"){const e=document.documentElement.lang;e&&e in s&&(l=e)}return l||(l=a),l};const r=(e,n=[])=>{if(typeof e==\\"object\\"){let o=e[n[0]]??e[\\"*\\"];typeof o==\\"number\\"&&(o=e[o]),e=o}return e?e.replace(/\\\\$([\\\\d$])/g,(o,t)=>t===\\"$\\"?\\"$\\":String(n[Number(t)-1]??\\"\\")):\\"\\"},f=e=>e.map((n,o)=>\`\${o}\${n.replace(/\\\\$/g,()=>\\"$$\\")}\`).join(\\"$\\").slice(1),u=\\"te_ST\\",$=\\"Test :-)\\",d={\\"hello $1\\":\\"Hello $1!\\",\\"worlds $1\\":{1:\\"world\\",\\"*\\":\\"worlds\\"}},m={locale:u,name:$,translations:d},g={te_ST:m},_=(e,n,o)=>{let t,c;do t=g[e],c=t.translations[n];while(!c&&(e=t.fallback));return c||(c=n),r(c,o)},p=(e,...n)=>{const o=i(),t=typeof e==\\"string\\"?e:f(e);return _(o,t,n)},w=p,y=\\"world\\";console.log(w\`hello \${y}\`);
"const s={te_ST:"Test :-)"};let a="te_ST",l,i=()=>{if(l)return l;if(typeof document<"u"){const e=document.documentElement.lang;e&&e in s&&(l=e)}return l||(l=a),l};const r=(e,n=[])=>{if(typeof e=="object"){let o=e[n[0]]??e["*"];typeof o=="number"&&(o=e[o]),e=o}return e?e.replace(/\\$([\\d$])/g,(o,t)=>t==="$"?"$":String(n[Number(t)-1]??"")):""},f=e=>e.map((n,o)=>\`\${o}\${n.replace(/\\$/g,()=>"$$")}\`).join("$").slice(1),u="te_ST",$="Test :-)",d={"hello $1":"Hello $1!","worlds $1":{1:"world","*":"worlds"}},m={locale:u,name:$,translations:d},g={te_ST:m},_=(e,n,o)=>{let t,c;do t=g[e],c=t.translations[n];while(!c&&(e=t.fallback));return c||(c=n),r(c,o)},p=(e,...n)=>{const o=i(),t=typeof e=="string"?e:f(e);return _(o,t,n)},w=p,y="world";console.log(w\`hello \${y}\`);
"
`)

Expand All @@ -121,13 +121,13 @@ test('noInline SSR', async () => {
expect(index.code).toContain('Test :-)')
expect(index.code).toContain('worlds $1')
expect.soft(index.code).toMatchInlineSnapshot(`
"const localeNames = { \\"te_ST\\": \\"Test :-)\\" };
let defaultLocale = \\"te_ST\\";
"const localeNames = { "te_ST": "Test :-)" };
let defaultLocale = "te_ST";
let currentLocale;
let getLocale = () => {
if (currentLocale)
return currentLocale;
if (typeof document !== \\"undefined\\") {
if (typeof document !== "undefined") {
const lang = document.documentElement.lang;
if (lang && lang in localeNames)
currentLocale = lang;
Expand All @@ -137,25 +137,25 @@ test('noInline SSR', async () => {
return currentLocale;
};
const interpolate = (tr, params = []) => {
if (typeof tr === \\"object\\") {
let resolved = tr[params[0]] ?? tr[\\"*\\"];
if (typeof resolved === \\"number\\")
if (typeof tr === "object") {
let resolved = tr[params[0]] ?? tr["*"];
if (typeof resolved === "number")
resolved = tr[resolved];
tr = resolved;
}
return tr ? tr.replace(
/\\\\$([\\\\d$])/g,
(_2, i) => i === \\"$\\" ? \\"$\\" : String(params[Number(i) - 1] ?? \\"\\")
) : \\"\\";
/\\$([\\d$])/g,
(_2, i) => i === "$" ? "$" : String(params[Number(i) - 1] ?? "")
) : "";
};
const makeKey = (tpl) => tpl.map((s, i) => \`\${i}\${s.replace(/\\\\$/g, () => \\"$$\\")}\`).join(\\"$\\").slice(1);
const locale = \\"te_ST\\";
const name = \\"Test :-)\\";
const makeKey = (tpl) => tpl.map((s, i) => \`\${i}\${s.replace(/\\$/g, () => "$$")}\`).join("$").slice(1);
const locale = "te_ST";
const name = "Test :-)";
const translations = {
\\"hello $1\\": \\"Hello $1!\\",
\\"worlds $1\\": {
\\"1\\": \\"world\\",
\\"*\\": \\"worlds\\"
"hello $1": "Hello $1!",
"worlds $1": {
"1": "world",
"*": "worlds"
}
};
const _0 = {
Expand All @@ -164,7 +164,7 @@ test('noInline SSR', async () => {
translations
};
const store = {
\\"te_ST\\": _0
"te_ST": _0
};
const _runtime = (locale2, key, params) => {
let s, tr;
Expand All @@ -178,11 +178,11 @@ test('noInline SSR', async () => {
};
const localize = (strOrTemplate, ...params) => {
const locale2 = getLocale();
const key = typeof strOrTemplate === \\"string\\" ? strOrTemplate : makeKey(strOrTemplate);
const key = typeof strOrTemplate === "string" ? strOrTemplate : makeKey(strOrTemplate);
return _runtime(locale2, key, params);
};
const _ = localize;
const n = \\"world\\";
const n = "world";
console.log(_\`hello \${n}\`);
"
`)
Expand All @@ -200,15 +200,15 @@ test('exports', async () => {
) as Rollup.OutputChunk
expect(index).toBeTruthy()
expect.soft(index.code).toMatchInlineSnapshot(`
"const e={te_ST:\\"Test :-)\\"};let l=\\"te_ST\\",t=\\"__$LOCALE$__\\";console.log(l,t,e);
"const e={te_ST:"Test :-)"};let l="te_ST",t="__$LOCALE$__";console.log(l,t,e);
"
`)
const testIndex = result.output.find(
o => o.fileName === 'te_ST/exports.js'
) as Rollup.OutputAsset
expect(testIndex).toBeTruthy()
expect.soft(testIndex.source).toMatchInlineSnapshot(`
"const e={te_ST:\\"Test :-)\\"};let l=\\"te_ST\\",t=\\"te_ST\\";console.log(l,t,e);
"const e={te_ST:"Test :-)"};let l="te_ST",t="te_ST";console.log(l,t,e);
"
`)
})
Expand All @@ -220,7 +220,7 @@ test('store', async () => {
) as Rollup.OutputAsset
expect(testIndex).toBeTruthy()
expect.soft(testIndex.source).toMatchInlineSnapshot(`
"const t={te_ST:{translations:{}}};let a=\\"te_ST\\";const s=(o,n=a)=>{if(!t[n])throw new Error(\`loadTranslations: Invalid locale \${n}\`);Object.assign(t[a].translations,o)};s({hi:\\"hello\\"},\\"te_ST\\");
"const t={te_ST:{translations:{}}};let a="te_ST";const s=(o,n=a)=>{if(!t[n])throw new Error(\`loadTranslations: Invalid locale \${n}\`);Object.assign(t[a].translations,o)};s({hi:"hello"},"te_ST");
"
`)
})
48 changes: 26 additions & 22 deletions src/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export let currentLocale${shouldInline ? ' = "__$LOCALE$__"' : ''}
${
shouldInline
? // These functions shouldn't be called from client code
`
`
export let getLocale = () => "__$LOCALE$__"
export const setDefaultLocale = () => {}
export const setLocaleGetter = () => {throw new Error('Do not call setLocaleGetter() in client code, use the html lang attribute or setDefaultLocale() (which only works in dev mode)')}
Expand Down Expand Up @@ -256,30 +256,34 @@ export const setLocaleGetter = fn => {
enforce: 'post',

// Emit the translated files as assets under locale subdirectories
generateBundle(_options, bundle) {
// console.log('generateBundle', _options, bundle, shouldInline)
if (!shouldInline) return
for (const [fileName, chunk] of Object.entries(bundle)) {
if (assetsDir && !fileName.startsWith(assetsDir)) continue
for (const locale of locales!) {
const newFilename = assetsDir
? `${assetsDir}${locale}/${fileName.slice(assetsDir.length)}`
: `${locale}/${fileName}`
let source = chunk.type === 'asset' ? chunk.source : chunk.code
if (fileName.endsWith('js') && typeof source === 'string') {
source = replaceGlobals({
code: source,
locale,
translations,
generateBundle: {
// enforce isn't enough to make hooks be post, so we need to set the order
order: 'post',
handler(_options, bundle) {
// console.log('generateBundle', _options, bundle, shouldInline)
if (!shouldInline) return
for (const [fileName, chunk] of Object.entries(bundle)) {
if (assetsDir && !fileName.startsWith(assetsDir)) continue
for (const locale of locales!) {
const newFilename = assetsDir
? `${assetsDir}${locale}/${fileName.slice(assetsDir.length)}`
: `${locale}/${fileName}`
let source = chunk.type === 'asset' ? chunk.source : chunk.code
if (fileName.endsWith('js') && typeof source === 'string') {
source = replaceGlobals({
code: source,
locale,
translations,
})
}
this.emitFile({
type: 'asset',
fileName: newFilename,
source,
})
}
this.emitFile({
type: 'asset',
fileName: newFilename,
source,
})
}
}
},
},

buildEnd() {
Expand Down

0 comments on commit 1a11b01

Please sign in to comment.