robisim74 / qwik-speak Goto Github PK
View Code? Open in Web Editor NEWTranslate your Qwik apps into any language
Home Page: https://robisim74.gitbook.io/qwik-speak/
License: MIT License
Translate your Qwik apps into any language
Home Page: https://robisim74.gitbook.io/qwik-speak/
License: MIT License
Hi everyone,
thank you so much for this awesome package.
if you have an optional value like this:
const number = useSignal<number>()
const p = usePlural()
return <div>{p(number.value ?? 0,'app.someKey')}</div>
It seems to me, you extract 0 as key here, which is wrong. This way extract is creating 0.json file for each language containing:
{
"0": {
"one": "",
"other": ""
}
}
I hope in the future I find some time to help you guys out, I really like the approach and except this small issue it works already quite fine.
Hi,
I have found something odd happening when going from /path/with/params/A
to /path/with/params/B
Imagine a route with parameters.
This route uses Speak component in order to load runtimeAssets that depend on the route parameter.
SPA-navigating to the same route but with different params will not load the new assets.
I believe this useTask is not re-executed when the component does not change (not really understanding Qwik internals and what/when a component gets recreated)
Small example:
// /src/routes/path/with/params/[param]/index.tsx
export default component$(() => {
const loc = useLocation();
const asset = `build-runtime-asset-${loc.params.param}`; // <- if you console log this, you will see it changes on SPA navigation
return (
{/* The runtime assets are loaded only the first time */}
<Speak runtimeAssets={[asset]}>
<ComponentPage></ComponentPage>
</Speak>
)
});
To reproduce this error, I have created a simple qwik project at the following GitHub repository: https://github.com/DongwonTTuna/qwik-speak-ErrExample.git.
npm install && npm run dev
to confirm that it works as expected.npm run build
to confirm that an error occurs.npm run qwik-speak-extract
to confirm that the contents of each json file are overwritten with values in a different language other than the default values. (this may need to run the command several times with original i18n files)Thank you!
all tranlate data are runtime asset
i want update the data for runtime json when the locale json has changed
I can now update the json when restarting the service, but I expect that no restart is required
Hi Robi,
first I would like to thank you for this great contribution. I was thinking about building a translation library for Qwik myself, but then found yours.
Currently I face the issue that the title and the description of the DocumentHead seems not to be translated. I added the runtime.json to the runtimeAssets in the config, but it stills shows the placeholder.
Do I miss something here?
One side note I always hated about ngx-translate that it is not type-safe. I was thinking about what to add to qwik-speak to make that feasible. I have had an own solution for Angular that uses a distributed-translate-loader-approach. Maybe we could customize the useTranslate hook to give back a function t that expects a dot-seperated string which matches the keys from the json that is used in the current scope. Especially for large projects that might be a better solution. Drawback is that we could only use the default language, but we could implement an unittest that checks wether the structure of the jsons is equal over all languages.
What do you think?
Sebastian
Hello,
I currently have the error above when using the library.
"version": "0.14.0",
"qwik": "1.1.4",
"qwik-city": "1.1.4"
QWIK ERROR Error: Code(3): Only primitive and object literals can be serialized
at createError (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:108:17)
at logError (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:102:54)
at logErrorAndStop (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:112:17)
at qError (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:185:12)
at eval (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:2639:15)
at Array.map ()
at Module._pauseFromContexts (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:2603:32)
at beforeClose (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/server.mjs:451:52)
at eval (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:3626:28)
at eval (D:/Zankel-Engineering/webpage/zankel-engineering/node_modules/@builder.io/qwik/core.mjs:4111:25) [Function: translate]
Will try to update the lib, but I guess I have nearly the latest version. Do you have an idea what that is coming from?
I get this warning before:
Qwik Speak warn Locale not resolved. Fallback to default locale: de-DE
Sebastian
Hello.
I'm using the latest version of qwik and qwik-speak.
Qwik-speak was configured using the quick start guide and works great locally, but when I build and deploy to a node express server, the translation breaks when navigating to another page via Link (SPA).
Could you help me?
Currently there is no documentation how to unit test a Qwik component using qwik-speak
and no test utilities either.
Reference https://dev.to/manuartero/testing-a-react-context-provider-5cfg
TestComponent.tsx
like belowimport { component$ } from '@builder.io/qwik';
import { $translate } from 'qwik-speak';
export const TestComponent = component$(() => {
return <h1>{$translate('banana_key')}</h1>;
});
speak-config.ts
like belowimport { $ } from '@builder.io/qwik';
import { isServer } from '@builder.io/qwik/build';
import type { LoadTranslationFn, SpeakConfig, TranslationFn } from 'qwik-speak';
export const speakConfig: SpeakConfig = {
defaultLocale: { lang: 'nl-NL', currency: 'EUR', timeZone: 'Europe/Amsterdam' },
supportedLocales: [
{ lang: 'nl-NL', currency: 'EUR', timeZone: 'Europe/Amsterdam' },
{ lang: 'en-US', currency: 'EUR', timeZone: 'Europe/Amsterdam' },
],
assets: ['common'],
};
export const loadTranslation$: LoadTranslationFn = $(async (lang: string, asset: string, origin?: string) => {
if (import.meta.env.DEV) {
let url = '';
// Absolute urls on server
if (isServer && origin) {
url = origin;
}
url += `/assets/i18n/${lang}/${asset}.json`;
const data = await fetch(url);
return data.json();
}
return Promise.resolve();
});
export const translationFn: TranslationFn = {
loadTranslation$,
};
it('should translate', async () => {
const Wrapper = component$(() => {
/**
* There are 2 choices here:
* - Either developers would provide a stub loadTranslationFn
* - Or in `speak-config.ts`, developers need to add extra logic to ensure translations are loaded in test environment
*/
const loadTranslationStub$ = $(() => {
// We can make this to return a JSON file as well
return Promise.resolve({
banana_key: 'banana',
});
});
return (
<QwikSpeak
config={speakConfig}
translationFn={{
loadTranslation$: loadTranslationStub$,
}}
>
<TestComponent />
</QwikSpeak>
);
});
const { screen, render } = await createDOM();
await render(<Wrapper />);
expect(screen.querySelector('h1')?.textContent).toBe('banana');
});
qwik-speak
. The wrapper component would be like Wrapper
in the example.loadTranslation$
property of translationFn
, see the example above.From the discussion at f7d5920#r98961952, I think there should be:
Maybe qwik-speak
can expose a wrapper component for unit test which provides:
qwik-speak
can be the children of it which allows them to access SpeakContext
loadTranslation$
in such a way that it would work for dev, prod as well as testThe whole message is:
Internal server error: Code(20): Calling a 'use*()' method outside 'component$(() => { HERE })' is not allowed. 'use*()' methods provide hooks to the 'component$' state and lifecycle, ie 'use' hooks can only be called synchronously within the 'component$' function or another 'use' method. For more information see: https://qwik.builder.io/docs/components/tasks/#use-method-rules
and stack trace points to "placeholder attribute prop"
I am using "qwik-speak": "^0.13.0" but it started in previous versions.
<Input
// this does not work any more
placeholder={t('app.enterYourEmail@@Enter your email')}
/>`
`
but this is ok
`const inputPlaceholderMsg = t('app.enterYourEmail@@Enter your email');
<Input
placeholder={inputPlaceholderMsg}
/>`
I wonder how to useTranslate
out of component$
/* eslint-disable @typescript-eslint/no-unused-vars */
import { $, component$ } from '@builder.io/qwik';
import { routeLoader$, z } from '@builder.io/qwik-city';
import type { InitialValues, SubmitHandler } from '@modular-forms/qwik';
import { formAction$, useForm, zodForm$ } from '@modular-forms/qwik';
const loginSchema = z.object({
email: z
.string()
.min(1, 'Please enter your email.') // =====> how to get localized message out of component ?
.email('The email address is badly formatted.'),
password: z
.string()
.min(1, 'Please enter your password.')
.min(8, 'You password must have 8 characters or more.'),
});
type LoginForm = z.infer<typeof loginSchema>;
export const useFormLoader = routeLoader$<InitialValues<LoginForm>>(() => ({
email: '',
password: '',
}));
// loginSchema can not move into component$ because useFormLoader refers loginSchema and should exported see https://qwik.builder.io/docs/route-loader/
export default component$(() => {
const [loginForm, { Form, Field }] = useForm<LoginForm>({
validate: zodForm$(loginSchema),
});
return <Form></Form>;
});
inlineTranslate
function needs to get locale context , also not work out of component
app build fails after upgrading @builder.io/qwik to 0.19.1 or 0.19.2
error
[vite] Internal server error: 'get' on proxy: property 'defaultLocale' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '#<Object>' but got '#<Object>')
Hi @robisim74,
First of all, thank you very much for all your effort and for offering us Qwik Speak.
When my component listings are rendered on the client while navigating through Qwik City's Link, do I need to include the runtimeAssets prop for it to work correctly?
The problem I encounter is that by adding runtimeAssets, the waiting time between page transitions increases significantly. In fact, I believe that currently it would take less time to query the page to the server than it takes for the resource to reach the browser and for Qwik Speak to perform the translations.
I'll leave a test repository here along with the corresponding deployments.
deploy without runtimeAssets -> https://speak-spa-runtime.vercel.app/
deploy with runtimeAssets -> https://speak-spa-runtime-git-withruntimeassets-joshxy.vercel.app/
Repo -> https://github.com/devagja/speak-spa-runtime
Thank you very much for everything!
Hello!
I am using this code in my app
{t('app.hello@@Hello, visit my website {{link}}', { link: <a href="https://google.com/">Google</a> })}
but that translate this:
'Hello, visit my website [object Object]'
What am I doing wrong? What is the correct way?
Thanks
I followed all instructions on the quick start till the end of the page but in the entry.ssr.tsx file I get the error that "isDev" is not defined.
Hi! I'm using qwik-speak with the inline plugin, and I'm getting the following error when building for production:
It only fails with version 0.12.1, and works with previous version
computing gzip size (0)...[vite-plugin-qwik-speak-inline] Cannot read properties of undefined (reading 'value')
✓ built in 3.56s
error during build:
TypeError: Cannot read properties of undefined (reading 'value')
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1731)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1907)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
at $ (/home/juan/Projects/every/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/qwik-speak/inline/index.cjs:6:1686)
ELIFECYCLE Command failed with exit code 1.
ELIFECYCLE Command failed with exit code 1.
I'm attempting to dynamically load values and then translate them in a loop within template as to offer a select menu with dynamic options. Take following example:
// i18n/LANG/app.json
{
"termA": "Value for term A",
"termB": "Value for term B",
"termC": "Value for term C",
// componens.tsx
const TERMS = ["A", "B", "C"];
return (
<select>
{TERMS.map((term) => <option>{translate(`term${term`)}</option>)}
</select>
);
The end results show up the terms without being translated. I tested this scenario in qwik-speak 0.0.5-0.0.8 and it was consistent.
As to workaround this problem, I found translating the values outside of template, in a loop, does work such as:
// const TERMS...
const VALUES = TERMS.map((term) => translate(`term${term}`));
// ...
<select>
{VALUES.map((value) => <option>{value}</option>)}
</select>
Hi @robisim74
I just noticed that $plural
API doesn't support param interpolation. Is it something missing or I misunderstand the API? I have the json
"devs": {
"one": "{{ value }} software developer {{ name }}",
"other": "{{ value }} software developers {{ name }}"
}
and when I look at $plural
API, there is no way to pass value for name
.
Another small thing is, I think prefix
param name in $plural
should be renamed to key
to be clearer.
Originally posted by @ahnpnl in #29 (reply in thread)
Optional [...lang]
parameter breaks the app using Express.js: QwikDev/qwik#1085
Temporary added a redirect to [lang]
in the app
Hi Robi,
might also be an issue on my side. But I don't know where.
Please see attached screenshot after a route change the translation for a json key is always undefined.
Do you have an idea. This behaviour only occurs in the prod build.
You can also see it here:
https://1eedbbba.zankel-engineering.pages.dev/
Sebastian
Hi! I'm trying to get translation using a dynamic key, like this:
https://github.com/juanpmarin/qwik-speak-repro/blob/0d0e053b1f92e08c3d7ca495b3926dda60b4ccee/src/components/list/list.tsx#L13
It works in development but no in production, you can see the bug here:
https://qwik-speak-repro.pages.dev/test/
If you press the Add item button, translation stop working
Howdy,
we have the following;
export const TextInput = component$(
({ value, label, error, ...props }: TextInputProps) => {
const { name, required } = props;
return (
<div class={clsx("form-control w-full mt-4", props.class)}>
<InputLabel name={name} label={label} required={required} />
<input
{...props}
class={clsx("input input-bordered w-full",
error
? "border-red-600/50 dark:border-red-400/50"
: ""
)}
id={name}
value={value || ""}
aria-invalid={!!error}
aria-errormessage={`${name}-error`}
/>
<InputError name={name} error={error} />
</div>
);
}
);
our template uses;
<Field name="code">
{(field, props) => (
<TextInput {...props} value={field.value} error={field.error} type="text" label="code" required />
)}
</Field>
if we do the following;
label={t('crm.countries.input.code@@code')}
we get the following error
[vite] Internal server error: Code(20): Calling a 'use*()' method outside 'component$(() => { HERE })' is not allowed. 'use*()' methods provide hooks to the 'component$' state and lifecycle, ie 'use' hooks can only be called synchronously within the 'component$' function or another 'use' method.
For more information see: https://qwik.builder.io/docs/components/lifecycle/#use-method-rules
any ideas...
Thanks upfront
Hello, thank you for all your work. I am trying to generate a static website but on "npm run build", the dist directory is generated but without "index.html". I tried again outside of my project, by pulling the qwik-speak repository and using SSG, however, this is not working. The steps as follow:
Setup qwik-speak repository:
git clone https://github.com/robisim74/qwik-speak.git
cd qwik-speak
npm install
Set SSG adapter:
npm run qwik add
Update speak-functions.ts by adding:
/**
* Dynamic SSG route
*/
export const onStaticGenerate: StaticGenerateHandler = () => {
return {
params: config.supportedLocales.map(locale => {
return { lang: locale.lang !== config.defaultLocale.lang ? locale.lang : '' };
})
};
};
Build:
npm run build
Maybe I miss understood something on https://robisim74.gitbook.io/qwik-speak/library/adapters
. Those files are generated in "dist": "favicon.svg _headers manifest.json q-manifest.json robots.txt service-worker.js". Also "dist/build" folder contains "en-US" and "it-IT" folders surrounded by a lot of js files.
How to properly use SSG using qwik-speak?
Hi!
I'm using a translation like this one:
{t("test.translation@@Envío para {{recipient}}", {
recipient: remoteData.value.embed?.foo,
})}
When I use the optional operator ?, translation fails when ran on client side, as compiled code is referencing a non existing variable, for example:
{t("test.translation@@Envío para {{recipient}}", {
recipient: remoteData.value.embed?.foo,
})}
Compiles to:
import { N as o } from "./q-767952c7.js";
import "./q-3c25f3f0.js";
import { useRemoteData as r } from "./q-c4196f84.js";
import "./q-4012d65d.js";
const p = () => {
var t;
const e = r();
return o("div", null, null, `Envío para ${te.value.embed}`, 1, "sB_0");
};
export { p as s_BP0CpRo5x74 };
As you can see, te
does not exists
On the other side:
{t("test.translation@@Envío para {{recipient}}", {
recipient: remoteData.value.embed.foo,
})}
Compiles to:
import { N as e } from "./q-767952c7.js";
import "./q-3c25f3f0.js";
import { useRemoteData as o } from "./q-d79a8c36.js";
import "./q-c200c11c.js";
const m = () => {
const t = o();
return e("div", null, null, `Envío para ${t.value.embed.foo}`, 1, "sB_0");
};
export { m as s_BP0CpRo5x74 };
You can find code to reproduce the error here:
https://github.com/juanpmarin/qwik-speak-repro/blob/4298ba760b2b05bc4852a6cf21fa7e0b0e8b9646/src/routes/test/%5Bid%5D/index.tsx#L17-L21
Due to this Qwik City bug: QwikDev/qwik#1016
Navigation temporarily disabled.
Dear qwik-speak developer,
Allow me to start by thanking you for the effort and dedication put into creating this exceptional plugin, whose contribution has been immense.
I am reaching out to you because I have experienced a problem when trying to execute the "build" or "preview" functions of QwikJS. The issue lies in an error that arises with vite-plugin-qwik-speak-inline. Specifically, the error message reflects: "ENOENT: no such file or directory, scandir '/src/translations/en'".
This error does not appear in the "dev" development mode of QwikJS, which has led me to carry out a more detailed diagnosis. I found that the root of the problem is that the qwik-speak's vite-plugin-qwik-speak-inline plugin does not recognize ".json" files located in subfolders. An example of this is "src/translates/en/contact/contact.json". Despite it working correctly in the "dev" mode of QwikJS.
In other words, the vite-plugin-qwik-speak-inline plugin does not support nesting of folders, which, from my perspective, would be a substantial improvement. This capability would allow for a more efficient organization of the folder and file structure. Without it, we are forced to host all JSON files within a single folder, which can become confusing, especially in medium to large sized applications.
I would greatly appreciate it if you could provide me with some guidance on how to tackle this issue. Attached below is a code snippet that reflects the current configuration of qwik-speak in my application.
Once again, thank you for your commitment to creating this useful plugin. I am looking forward to your response.
import { server$ } from '@builder.io/qwik-city';
import { configuration } from '~/configuration';
import type { SpeakConfig, Translation, TranslationFn } from 'qwik-speak';
const translationFiles = import.meta.glob<Translation>(
'/src/translations/**/*.json'
);
function getAssets(): string[] {
const assets: string[] = [];
for (const path of Object.keys(translationFiles)) {
let finalPath = path;
for (const language of configuration.i18n.language.available) {
finalPath = finalPath.replace(`/src/translations/${language}`, '');
}
if (!finalPath.startsWith('/')) {
finalPath = `/${finalPath}`;
}
if (!assets.includes(finalPath) && !finalPath.endsWith('runtime.json')) {
assets.push(finalPath);
}
}
return assets;
}
export const speakConfig: SpeakConfig = {
assets: getAssets(),
defaultLocale: {
lang: configuration.i18n.language.default,
},
runtimeAssets: ['/runtime/runtime.json'],
supportedLocales: configuration.i18n.language.available.map((language) => ({
lang: language,
})),
};
export const translationFunction: TranslationFn = {
loadTranslation$: server$(async (language: string, asset: string) => {
return translationFiles[`/src/translations/${language}${asset}`]();
}),
};
My application gets user config on load to get user's default locale and supported locales. I have a default speakConfig
like below
{
defaultLocale: { lang: 'en-US' },
supportedLocales: [{ lang: 'en-US' }],
assets: ['common'],
}
I tried 2 attempts:
QwikSpeakProvider
and pass a reactive store data into my wrapper component. The reactive store data is set based on API response. However, this way doesn't work.useSpeakContext
. For example speakContext.config.supportedLocales = [{ lang: 'en-US' }, { lang: 'nl-NL' }]
. This way doesn't work eitherA new feature to allow config to be dynamic configured or if new feature is not possible, maybe some documentation updates?
Originally posted by @Zankel-Engineering in #55 (comment)
When a qwik app made with an express or fastify adapter is build in production, the page loads translated until there is a rerender of the component. Only the component turns in to the default lang
This is reproducible as followed:
created qwik app with npm create qwik@latest
add express or fastify adapter like described here: https://qwik.builder.io/docs/deployments/node/
add qwik speak following the quick start: https://github.com/robisim74/qwik-speak/blob/main/docs/quick-start.md
example component with state and translations:
import { $, component$, useSignal } from '@builder.io/qwik';
import type { SpeakLocale } from 'qwik-speak';
import { useSpeakConfig, useSpeakLocale, useTranslate } from 'qwik-speak';
export const ChangeLocale = component$(() => {
const t = useTranslate();
const locale = useSpeakLocale();
const config = useSpeakConfig();
const isOpen = useSignal(false);
const changeLocale$ = $((newLocale: SpeakLocale) => {
// Store locale in a cookie
document.cookie = `locale=${JSON.stringify(
newLocale
)};max-age=86400;path=/`;
location.reload();
});
const getLocaleTranslation = (lang: SpeakLocale['lang']) => {
switch (lang) {
case 'en-US':
return t('app.english');
case 'nl-NL':
return t('app.dutch');
case 'pl-PL':
return t('app.polish');
default:
return null;
}
};
return (
<>
<div class="relative inline-block text-left gap-x-4 px-6 py-3 text-sm font-semibold leading-6 text-gray-900">
<div>
<button
type="button"
class="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
id="menu-button"
aria-expanded="true"
aria-haspopup="true"
onClick$={() => (isOpen.value = !isOpen.value)}
>
{getLocaleTranslation(locale.lang)}
<svg
class="-mr-1 h-5 w-5 text-gray-400"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
{isOpen.value && (
<div
class="absolute left-6 bottom-16 z-10 mt-2 w-56 origin-bottom-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
role="menu"
aria-orientation="vertical"
aria-labelledby="menu-button"
tabIndex={-1}
>
<div class="py-1" role="none">
{config.supportedLocales.map((value) => {
return (
<>
<a
key={value.lang}
onClick$={async () => await changeLocale$(value)}
class="text-gray-700 group flex items-center px-4 py-2 text-sm hover:text-emerald-600 hover:bg-gray-50 cursor-pointer"
role="menuitem"
tabIndex={-1}
id="menu-item-0"
>
{getLocaleTranslation(value.lang)}
</a>
</>
);
})}
</div>
</div>
)}
</div>
</>
);
});
If you need more from me, please tell me
I've made a playground with your package. I copied pretty much everything from your sample app, but I did some changes to always show the locale in the URL, instead of hiding it when it's the default.
https://github.com/frederikstonge/qwik-playground
When I change from English to French, and then I press back, it changes the URL back to English, but the site remains in French.
Either I'm doing something wrong, but onGet in layout.tsx isn't called at all, and I can't use the speak context.
For the qwik project deployed by ssg, switching to other languages does not take effect
Hello.
Using qwik-speak
against newly created app that is using Qwik 0.0.39, and implement locale changing such as:
onClick$={async () => await changeLocale(locale, ctx)}>
results in the following eslint warning:
[eslint] Identifier ("ctx") can not be captured inside the scope (onClick$) because "ctx.translateFn.getTranslation$" is a function, which is not serializable. Check out https://qwik.builder.io/docs/advanced/optimizer for more details. [qwik/valid-lexical-scope]
though, it seems to be working alright.
Would changing to using something like ctx.setLocale(locale)
suppress this warning? I was looking into the lib code and there doesn't seem to be any blocker to moving that functionality to the context itself rather than creating a utility function for it.
Hi,
I'm having an issue with qwik speak whenever I try to deploy to Netlify
It's like the whole deploy is broken it doesn't even load images but whenever I remove qwik speak it works
Workaround: disable trailingSlash
Qwik City option in Vite config:
qwikCity({ trailingSlash: false })
Reference: QwikDev/qwik#2262
Hi Robi,
I saw that internally the useServerData hook is used. I checked the code of Qwik in the node_modules. It is kinda cryptic. But I don't have so much time today to try to clone the Qwik repo and understand what is going on under the hood. So I am not sure what they are doing and if that is a point.
But why we don't use the Accept-Language header to get a grasp of the browser language in a routeLoader? That should also work in development where I always get the lib falling back to the default.
Serverlanguage might not be the correct here.
Just an idea. Don't know if it is valid. I will go to the Gym now and spend a little bit time with my wife :-). Was sitting in front of the computer all day again. But I want to try to get everything out of the framework with the zankel-engineering website. As soon as I am 80% satisfied with it and it is deployable I will make it public so that people even less experienced that Iam can maybe get a couple of ideas from it.
Qwik feels to me a little bit unstructured for enterprise grade applications. Maybe that is also a point where some companies could have a need for consulting in the future. Error reporting is also really bad. But he, it is open source and I am happy and thankful that somebody puts in the time to make something like this available. I never had the feeling that doing much open source as a small freelancer would be worth it. Anyway. Hear you soon.
Sebastian
Hello there and thanks in advance.
Could you please state in the README (or anywhere else you want) the main reasons why someone would this library instead of $localize?
Thanks!
There is an issue in the console when trying to use translation in a component that is described by a storybook:
Error: Code(20): Calling a 'use*()' method outside 'component$(() => { HERE })' is not allowed. 'use*()' methods provide hooks to the 'component$' state and lifecycle, ie 'use' hooks can only be called syncronously within the 'component$' function or another 'use' method.
For more information see: https://qwik.builder.io/docs/components/lifecycle/#use-method-rules
at createError (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:70:17)
at logError (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:64:54)
at logErrorAndStop (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:74:17)
at qError (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:137:12)
at useInvokeContext (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:1345:15)
at useSequentialScope (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:1488:18)
at useContext (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2593:39)
at useSpeakContext (http://localhost:6006/node_modules/qwik-speak/lib/index.qwik.mjs?v=e630c39b:65:29)
at $translate (http://localhost:6006/node_modules/qwik-speak/lib/index.qwik.mjs?v=e630c39b:75:18)
at ViewAdventureSection (http://localhost:6006/src/components/adventure-card/adventure-card.tsx?t=1679334703890:348:23)
at invoke (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:1367:26)
at processNode (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2925:21)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2960:16)
at http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2970:55
at Array.flatMap (<anonymous>)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2970:40)
at processNode (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2933:21)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2960:16)
at processNode (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2926:16)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2960:16)
at http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2970:55
at Array.flatMap (<anonymous>)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2970:40)
at processNode (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2933:21)
at processData$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2960:16)
at http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:2884:34
at async Promise.all (index 1)
at async Promise.all (index 0)
at async renderRoot$1 (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:7187:9)
at async render (http://localhost:6006/node_modules/@builder.io/qwik/core.mjs?v=e630c39b:7178:23)
@robisim74 Hello again,
Your package is great in all use-case, even with MD/MDX files.
But web pages are reloaded every time changing locales, causes flickering effect, which is not smooth rendered.
location.href = url.toString();
How can we avoid this?
Please help & thanks much.
Hello,
I have finished rewriting my website from Angular to Qwik and I have been using Qwik Speak without any problems until now.
When building the app for production, I get an error:
vite v4.3.3 building for production... ✓ 2672 modules transformed. computing gzip size (0)...[vite-plugin-qwik-speak-inline] EMFILE: too many open files, open '\dist\build\nl\q-678594ab.js' ✓ built in 10.03s error during build: Error: EMFILE: too many open files, open '\dist\build\nl\q-678594ab.js'
This issue appears if I have too many supported languages set in qwikSpeakInline(). It works well with 4 languages set, but it will fail with 5+. I have a total of 14 supported languages, so this is an issue that must be fixed before I can deploy my app to production.
Hi, I just upgraded qwik to 1.1.4 and qwik-speak ^0.13.0 with inline translation:
For production build I'm getting the following error:
QWIK ERROR Error: Code(20)
Howdy,
with any fresh qwik install and following your quick install guide i end up with the following error;
20:01:48 [vite] Internal server error: translationData[langasset] is not a function
File: /IdeaProjects/dare-qwik-4/src/speak-functions.ts:13:5
11 | */
12 | const loadTranslation$: LoadTranslationFn = server$(async (lang: string, asset: string) =>
13 | await translationData[`/i18n/${lang}/${asset}.json`]()
| ^
14 | );
If i remove the asset: string and have it like
await translationData[
/i18n/${lang}/welcome.json]()
I use welcome because of the component;
export default component$(() => {
return (
<Speak assets={['welcome']}>
<Welcome />
</Speak>
);
});
it will work just fine
all the code is from the quick install, either i'm missing something or there is a bug...
Can somebody verify if there's a bug or i'm just overlooking something ^^
If I have following as my localised terms dictionary:
{
term: 'Term Value',
termWithParam: 'Term with {{term}}',
}
How can I get Term with Term Value
out of the two terms defined in terms dictionary? trying the following:
_('termWithParam', {term: _('term')})
would result in:
Term with [object Promise]
Hello.
Looks like adding qwik-speak
to Qwik app of version 0.12 causes two issues:
speak-config
where variables endpoint
, newSegment
should not be re-defined. I overcame this issue by changing the lines to following:// ...
export const loadTranslation$: LoadTranslationFn = $(
async (lang: string, asset: string, url?: URL) => {
if (import.meta.env.DEV || asset === "runtime") {
// Absolute urls on server
if (isServer && url) {
const endpoint = `${url.origin}/i18n/${lang}/${asset}.json`;
const data = await fetch(endpoint);
return data.json();
} else {
const endpoint = `/i18n/${lang}/${asset}.json`;
const data = await fetch(endpoint);
return data.json();
}
}
}
);
// ...
export const storeLocale$: StoreLocaleFn = $((locale: SpeakLocale) => {
// Store locale in cookie
document.cookie = `locale=${JSON.stringify(locale)};path=/`;
// Localize the route
const url = new URL(document.location.href);
if (url) {
const pathLang = config.supportedLocales.find((x) =>
url.pathname.startsWith(`/${x.lang}`)
)?.lang;
const regex = new RegExp(`(/${pathLang}/)|(/${pathLang}$)`);
const segment = url.pathname.match(regex)?.[0];
if (pathLang && segment) {
if (locale.lang !== config.defaultLocale.lang) {
const newSegment = segment.replace(pathLang, locale.lang);
url.pathname = url.pathname.replace(segment, newSegment);
} else {
const newSegment = "/";
url.pathname = url.pathname.replace(segment, newSegment);
}
} else if (locale.lang !== config.defaultLocale.lang) {
url.pathname = `/${locale.lang}${url.pathname}`;
}
window.history.pushState({}, "", url);
}
});
export const speakConfig: SpeakConfig = {
defaultLocale: { lang: 'en-US' },
supportedLocales: [{ lang: 'en-US' }],
assets: ['common'],
};
loadTranslation$
like belowexport const loadTranslation$: LoadTranslationFn = $(async (lang: string, asset: string, origin?: string) => {
let url = '';
// Absolute urls on server
if (isServer && origin) {
url = origin;
}
url += `/assets/i18n/${lang}/${asset}.json`;
let data: object | null = null;
try {
const response = await fetch(url);
data = await response.json();
} catch (error) {
// Implement error handling here
console.log('loadTranslation$ error: ', error);
}
return data;
});
changeLocale
like belowexport const Header = component$(() => {
const ctx = useSpeakContext();
return (
<header>
<div className={'header-banner'}></div>
<button onClick$={() => changeLocale({ lang: 'nl-NL' }, ctx)}>Change locale</button>
</header>
);
});
What I noticed was, when I clicked the button to execute changeLocale
, the loadTranslation$
didn't execute which took me a while to notice that my speak config didn't include locale nl-NL
.
Can we make loadTranslation$
execute in this case so that the catch
can log something?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.