Qwik Speak
  • README
  • Library
    • Quick Start
    • Tutorial: localized routing with the language
    • Tutorial: translated routing with url rewriting
    • Translate
    • Translation functions
    • Lazy loading translation
    • Qwik Speak and Adapters
    • Testing
  • Tools​
    • Qwik Speak Extract
    • Qwik Speak Inline Vite plugin
Powered by GitBook
On this page
  • Vite plugin
  • Configuration
  • Resolve locale
  • Tutorials
Edit on GitHub
  1. Library

Quick Start

PreviousREADMENextTutorial: localized routing with the language

Last updated 1 year ago

Setup an app with Qwik Speak

npm install qwik-speak --save-dev

Vite plugin

Add in vite.config.ts:

import { qwikSpeakInline } from 'qwik-speak/inline';

export default defineConfig(() => {
  return {
    plugins: [
      qwikCity(),
      qwikVite(),
      qwikSpeakInline({
        supportedLangs: ['en-US', 'it-IT'],
        defaultLang: 'en-US',
        assetsPath: 'i18n'
      }),
      tsconfigPaths(),
    ],
  };
});

Configuration

Let's create speak-config.ts and speak-functions.ts files in src folder:

src/speak-config.ts

import type { SpeakConfig } from 'qwik-speak';

export const config: SpeakConfig = {
  defaultLocale: { lang: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' },
  supportedLocales: [
    { lang: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome' },
    { lang: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' }
  ],
  // Translations available in the whole app
  assets: [
    'app'
  ],
  // Translations with dynamic keys available in the whole app
  runtimeAssets: [
    'runtime'
  ]
};

src/speak-functions.ts

import { server$ } from '@builder.io/qwik-city';
import type { LoadTranslationFn, Translation, TranslationFn } from 'qwik-speak';

/**
 * Translation files are lazy-loaded via dynamic import and will be split into separate chunks during build.
 * Assets names and keys must be valid variable names
 */
const translationData = import.meta.glob<Translation>('/i18n/**/*.json');

/**
 * Using server$, translation data is always accessed on the server
 */
const loadTranslation$: LoadTranslationFn = server$(async (lang: string, asset: string) =>
  await translationData[`/i18n/${lang}/${asset}.json`]?.()
);

export const translationFn: TranslationFn = {
  loadTranslation$: loadTranslation$
};

loadTranslation$ is a customizable QRL function: you can load the translation files in the way you prefer

Add useQwikSpeak provider in root.tsx and pass it the configuration and the translation functions:

src/root.tsx

import { useQwikSpeak } from 'qwik-speak';
import { config } from "./speak-config";
import { translationFn } from "./speak-functions";

export default component$(() => {
  /**
   * Init Qwik Speak
   */
  useQwikSpeak({ config, translationFn });

  return (
    <QwikCityProvider>
      {/* ... */}
    </QwikCityProvider>
  );
});

Resolve locale

Create plugin.ts in the root of the src/routes directory:

src/routes/plugin.ts

import type { RequestHandler } from '@builder.io/qwik-city';
import { config } from '../speak-config';

/**
 * This middleware function must only contain the logic to set the locale,
 * because it is invoked on every request to the server.
 * Avoid redirecting or throwing errors here, and prefer layouts or pages
 */
export const onRequest: RequestHandler = ({ request, locale }) => {
  const acceptLanguage = request.headers?.get('accept-language');

  let lang: string | null = null;

  // Try to use user language
  if (acceptLanguage) {
    lang = acceptLanguage.split(';')[0]?.split(',')[0];
  }

  // Check supported locales
  lang = config.supportedLocales.find(value => value.lang === lang)?.lang || config.defaultLocale.lang;

  // Set Qwik locale
  locale(lang);
};

We're on the server here, and you can get the language from acceptLanguage, a cookie, or a URL parameter, as you like. But is mandatory to set the Qwik locale

Set the base URL for loading the chunks in the browser in entry.ssr.tsx file:

import { isDev } from '@builder.io/qwik/build';
import type { RenderOptions } from "@builder.io/qwik/server";
import { config } from './speak-config';

/**
 * Determine the base URL to use for loading the chunks in the browser.
 * The value set through Qwik 'locale()' in 'plugin.ts' is saved by Qwik in 'serverData.locale' directly.
 * Make sure the locale is among the 'supportedLocales'
 */
export function extractBase({ serverData }: RenderOptions): string {
  if (!isDev && serverData?.locale) {
    return '/build/' + serverData.locale;
  } else {
    return '/build';
  }
}

export default function (opts: RenderToStreamOptions) {
  return renderToStream(<Root />, {
    manifest,
    ...opts,
    // Determine the base URL for the client code
    base: extractBase,
    // Use container attributes to set attributes on the html tag
    containerAttributes: {
      lang: opts.serverData?.locale || config.defaultLocale.lang,
      ...opts.containerAttributes,
    },
  });
}

Tutorials

For more details, see

Qwik Speak Inline Vite plugin
Translation functions
Tutorial: localized routing with the language
Tutorial: translated routing with url rewriting