diff --git a/README.md b/README.md index e8702eb..2e809bc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Qwik Speak ⚡️ +# Qwik Speak ![logo](https://user-images.githubusercontent.com/14012361/230638591-98477fff-2c07-47fd-ac2a-cc5c81098f60.png) [![Node.js CI](https://github.com/robisim74/qwik-speak/actions/workflows/node.js.yml/badge.svg)](https://github.com/robisim74/qwik-speak/actions/workflows/node.js.yml) [![Playwright](https://github.com/robisim74/qwik-speak/actions/workflows/playwright.yml/badge.svg)](https://github.com/robisim74/qwik-speak/actions/workflows/playwright.yml) > Internationalization (i18n) library to translate texts, dates and numbers in Qwik apps @@ -158,6 +158,9 @@ Formats a relative time using [Intl.RelativeTimeFormat](https://developer.mozill - `formatNumber(value: number | string, options?: Intl.NumberFormatOptions, locale?: SpeakLocale, lang?: string, currency?: string)` Formats a number using [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) API +- `displayName(code: string, options: Intl.DisplayNamesOptions, locale?: SpeakLocale, lang?: string)` +Returns the translation of language, region, script or currency display names using [Intl.DisplayNames](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames) API + ## Development Builds ### Library & tools #### Build diff --git a/public/favicon.svg b/public/favicon.svg index 0ded7c1..b621341 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1 +1,17 @@ - \ No newline at end of file + + + + + + + + + + + + Layer 1 + + + + + \ No newline at end of file diff --git a/src/components/change-locale/change-locale.css b/src/components/change-locale/change-locale.css new file mode 100644 index 0000000..969a313 --- /dev/null +++ b/src/components/change-locale/change-locale.css @@ -0,0 +1,27 @@ +.change-locale { + margin-top: 10px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 20px; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16); + border-radius: 6px; +} + +.change-locale h2 { + margin-bottom: 20px; + font-weight: bold; + text-align: center; +} + +.change-locale .names { + display: flex; + justify-content: center; + align-items: center; +} + +.change-locale .names button.active { + background-color: #327335; + color: #fff; +} \ No newline at end of file diff --git a/src/components/change-locale/change-locale.tsx b/src/components/change-locale/change-locale.tsx index 90b0036..42fc8a6 100644 --- a/src/components/change-locale/change-locale.tsx +++ b/src/components/change-locale/change-locale.tsx @@ -1,7 +1,7 @@ import { $, component$, useStyles$ } from '@builder.io/qwik'; import { useLocation } from '@builder.io/qwik-city'; import type { SpeakLocale } from 'qwik-speak'; -import { $translate as t, useSpeakLocale, useSpeakConfig } from 'qwik-speak'; +import { $translate as t, displayName as dn, useSpeakLocale, useSpeakConfig } from 'qwik-speak'; import styles from './change-locale.css?inline'; @@ -32,12 +32,14 @@ export const ChangeLocale = component$(() => { return (

{t('app.changeLocale')}

- {config.supportedLocales.map(value => ( -
await navigateByLocale$(value)}> - {value.lang} -
- ))} +
+ {config.supportedLocales.map(value => ( + + ))} +
); }); diff --git a/src/components/header/change-locale.tsx b/src/components/header/change-locale.tsx deleted file mode 100644 index be3cbc3..0000000 --- a/src/components/header/change-locale.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { $, component$ } from '@builder.io/qwik'; -import { useLocation } from '@builder.io/qwik-city'; -import type { SpeakLocale } from 'qwik-speak'; -import { $translate as t, useSpeakLocale, useSpeakConfig } from 'qwik-speak'; - -export const ChangeLocale = component$(() => { - const loc = useLocation(); - - const locale = useSpeakLocale(); - const config = useSpeakConfig(); - - // Replace the locale and navigate to the new URL - const navigateByLocale$ = $((newLocale: SpeakLocale) => { - const url = new URL(location.href); - if (loc.params.lang) { - if (newLocale.lang !== config.defaultLocale.lang) { - url.pathname = url.pathname.replace(loc.params.lang, newLocale.lang); - } else { - url.pathname = url.pathname.replace(new RegExp(`(/${loc.params.lang}/)|(/${loc.params.lang}$)`), '/'); - } - } else if (newLocale.lang !== config.defaultLocale.lang) { - url.pathname = `/${newLocale.lang}${url.pathname}`; - } - - location.href = url.toString(); - }); - - return ( -
- {t('app.changeLocale')} - {config.supportedLocales.map(value => ( -
await navigateByLocale$(value)}> - {value.lang} -
- ))} -
- ); -}); diff --git a/src/components/header/header.css b/src/components/header/header.css index d6d69ee..5e4fb0f 100644 --- a/src/components/header/header.css +++ b/src/components/header/header.css @@ -1,52 +1,52 @@ -header { - background-color: #006fb3; -} - -header .header-inner { - display: grid; - grid-template-columns: 1fr auto; +.header { + display: flex; + align-items: center; + justify-content: space-between; padding: 10px; - max-width: 800px; - margin: 0 auto; } -header a { - color: white; - text-decoration: none; - padding: 4px 8px; - margin-right: 5px; - border-radius: 4px; +.logo { + width: 160px; } -header a:hover { - background-color: #ffffff30; +.header ul { + padding: 0; + margin: 0; + list-style: none; } -header .active { - background-color: #ffffff15; +.header li { + margin: 0; + padding: 0; + display: inline-block; } -.change-locale { - padding: 8px; - color: white; - display: flex; - align-items: center; - gap: 10px; +.header li a { + font-weight: 700; + color: #000000; + display: inline-block; + padding: 0 0.5em; + text-decoration: none; } -.change-locale .button { - color: white; - text-decoration: none; - padding: 4px 8px; - margin-right: 5px; - border-radius: 4px; - cursor: pointer; +.header li a:hover { + color: #3e8e41; } -.change-locale .button:hover { - background-color: #ffffff30; +.header li a.active { + color: #327335; } -.change-locale .active { - background-color: #ffffff15; +@media (min-width: 768px) { + .header { + padding: 20px 70px; + } + + .logo { + width: 200px; + } + + .header li a { + padding: 0 1em; + } } \ No newline at end of file diff --git a/src/components/header/header.tsx b/src/components/header/header.tsx index 4c98bce..3e9bc6d 100644 --- a/src/components/header/header.tsx +++ b/src/components/header/header.tsx @@ -2,7 +2,8 @@ import { component$, useStyles$ } from '@builder.io/qwik'; import { Link, useLocation } from '@builder.io/qwik-city'; import { $translate as t, useSpeakConfig, useSpeakLocale } from 'qwik-speak'; -import { ChangeLocale } from './change-locale'; +import { ChangeLocale } from '../change-locale/change-locale'; +import { SpeakLogo } from '../icons/speak'; import styles from './header.css?inline'; @@ -18,23 +19,29 @@ export const Header = component$(() => { }; return ( -
-
- - - -
-
+ + + + + ); }); diff --git a/src/components/icons/speak.tsx b/src/components/icons/speak.tsx new file mode 100644 index 0000000..59cb1ed --- /dev/null +++ b/src/components/icons/speak.tsx @@ -0,0 +1,20 @@ +export const SpeakLogo = () => ( + + + + + + + + + + + + Qwik + + Speak + + + + +); diff --git a/src/global.css b/src/global.css index a75d7a9..3871b14 100644 --- a/src/global.css +++ b/src/global.css @@ -1,12 +1,58 @@ body { - margin: 0; - padding: 0; - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', - sans-serif; + font-family: Arial, sans-serif; + font-size: 14px; + background-color: #f2f2f2; } main { - padding: 10px 20px; - max-width: 800px; margin: 0 auto; + padding: 10px 10px 50px 10px; + background-color: #fff; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16); + display: flex; + flex-direction: column; + border-radius: 6px; +} + +main .content { + padding: 10px; + text-align: center; +} + +button { + display: inline-block; + padding: 5px 10px; + margin: 5px 10px; + border-radius: 5px; + border-width: 1px; + background-color: #fff; + font-size: 14px; + text-decoration: none; +} + +button:hover { + background-color: #f2f2f2; + cursor: pointer; +} + +@media (min-width: 768px) { + body { + font-size: 16px; + } + + main { + max-width: 1000px; + padding: 20px; + } + + main .content { + padding: 20px 70px; + } + + button { + display: inline-block; + padding: 10px 20px; + font-size: 16px; + text-decoration: none; + } } \ No newline at end of file diff --git a/src/routes/[...lang]/index.tsx b/src/routes/[...lang]/index.tsx index 099a6f1..f886a11 100644 --- a/src/routes/[...lang]/index.tsx +++ b/src/routes/[...lang]/index.tsx @@ -16,7 +16,7 @@ export const Home = component$(() => { const count = useSignal(0); return ( - <> +

{t('app.title')}

{t('app.subtitle')}

@@ -27,8 +27,8 @@ export const Home = component$(() => {

{t('home.plural')}

-

{p(count.value, 'home.devs')}

+

{t('home.dates')}

{fd(Date.now(), { dateStyle: 'full', timeStyle: 'short' })}

@@ -38,7 +38,7 @@ export const Home = component$(() => {

{fn(1000000)}

{fn(1000000, { style: 'currency' })}

{fn(1, { style: 'unit', unit: units['length'] })}

- +
); }); diff --git a/src/routes/layout.tsx b/src/routes/layout.tsx index c07472c..a6d733e 100644 --- a/src/routes/layout.tsx +++ b/src/routes/layout.tsx @@ -6,12 +6,10 @@ import { config } from '../speak-config'; export default component$(() => { return ( - <> +
-
- -
- + +
); }); diff --git a/src/speak-config.ts b/src/speak-config.ts index 890c183..bfdb099 100644 --- a/src/speak-config.ts +++ b/src/speak-config.ts @@ -6,8 +6,8 @@ import type { SpeakConfig } from 'qwik-speak'; export const config: SpeakConfig = { defaultLocale: { lang: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles', units: { 'length': 'mile' } }, supportedLocales: [ - { lang: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome', units: { 'length': 'kilometer' } }, - { lang: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles', units: { 'length': 'mile' } } + { lang: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles', units: { 'length': 'mile' } }, + { lang: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome', units: { 'length': 'kilometer' } } ], assets: [ 'app' // Translations shared by the pages