Skip to content

Commit d43407c

Browse files
committed
Merge branch 'main' into feat/convert-npmjs-readme-urls-to-npmx
2 parents 66d9ee5 + 6a5d286 commit d43407c

64 files changed

Lines changed: 5718 additions & 578 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/autofix.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ jobs:
1717
runs-on: ubuntu-latest
1818

1919
steps:
20-
- uses: actions/checkout@v6
20+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2121
- run: corepack enable
22-
- uses: actions/setup-node@v6
22+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
2323
with:
2424
node-version: lts/*
2525
cache: 'pnpm'
@@ -30,6 +30,9 @@ jobs:
3030
- name: 📦 Install browsers
3131
run: pnpm playwright install
3232

33+
- name: 🌍 Update lunaria data
34+
run: pnpm build:lunaria
35+
3336
- name: 🔠 Fix lint errors
3437
run: pnpm lint:fix
3538

.github/workflows/ci.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ jobs:
1919
runs-on: ubuntu-latest
2020

2121
steps:
22-
- uses: actions/checkout@v6
22+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2323
- run: corepack enable
24-
- uses: actions/setup-node@v6
24+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
2525
with:
2626
node-version: lts/*
2727
cache: pnpm
@@ -36,9 +36,9 @@ jobs:
3636
runs-on: ubuntu-latest
3737

3838
steps:
39-
- uses: actions/checkout@v6
39+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
4040
- run: corepack enable
41-
- uses: actions/setup-node@v6
41+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
4242
with:
4343
node-version: lts/*
4444
cache: pnpm
@@ -64,9 +64,9 @@ jobs:
6464
image: mcr.microsoft.com/playwright:v1.57.0-noble
6565

6666
steps:
67-
- uses: actions/checkout@v6
67+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
6868
- run: corepack enable
69-
- uses: actions/setup-node@v6
69+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
7070
with:
7171
node-version: lts/*
7272
cache: pnpm
@@ -81,9 +81,9 @@ jobs:
8181
runs-on: ubuntu-latest
8282

8383
steps:
84-
- uses: actions/checkout@v6
84+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
8585
- run: corepack enable
86-
- uses: actions/setup-node@v6
86+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
8787
with:
8888
node-version: lts/*
8989
cache: pnpm
@@ -103,9 +103,9 @@ jobs:
103103
runs-on: ubuntu-latest
104104

105105
steps:
106-
- uses: actions/checkout@v6
106+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
107107
- run: corepack enable
108-
- uses: actions/setup-node@v6
108+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
109109
with:
110110
node-version: lts/*
111111
cache: pnpm

.github/workflows/lunaria.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ jobs:
2222

2323
steps:
2424
- name: Checkout
25-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2626
with:
2727
# Necessary for Lunaria to work properly
2828
# Makes the action clone the entire git history
2929
fetch-depth: 0
3030

3131
- run: corepack enable
32-
- uses: actions/setup-node@v6
32+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
3333
with:
3434
node-version: lts/*
3535
cache: pnpm

.github/workflows/provenance.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
check-provenance:
1717
runs-on: ubuntu-latest
1818
steps:
19-
- uses: actions/checkout@v6
19+
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2020
with:
2121
fetch-depth: 0
2222
- name: Check provenance downgrades

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ test-results/
3636

3737
# Lighthouse
3838
.lighthouseci
39+
40+
# generated files
41+
shared/types/lexicons

CONTRIBUTING.md

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,70 @@ const props = defineProps<{
208208

209209
Ideally, extract utilities into separate files so they can be unit tested. 🙏
210210

211+
## RTL Support
212+
213+
We support `right-to-left` languages, we need to make sure that the UI is working correctly in both directions.
214+
215+
Simple approach used by most websites of relying on direction set in HTML element does not work because direction for various items, such as timeline, does not always match direction set in HTML.
216+
217+
We've added some `UnoCSS` utilities styles to help you with that:
218+
219+
- Do not use `left/right` padding and margin: for example `pl-1`. Use `padding-inline-start/end` instead. So `pl-1` should be `ps-1`, `pr-1` should be `pe-1`. The same rules apply to margin.
220+
- Do not use `rtl-` classes, such as `rtl-left-0`.
221+
- For icons that should be rotated for RTL, add `class="rtl-flip"`. This can only be used for icons outside of elements with `dir="auto"`.
222+
- For absolute positioned elements, don't use `left/right`: for example `left-0`. Use `inset-inline-start/end` instead. `UnoCSS` shortcuts are `inset-is` for `inset-inline-start` and `inset-ie` for `inset-inline-end`. Example: `left-0` should be replaced with `inset-is-0`.
223+
- If you need to change the border radius for an entire left or right side, use `border-inline-start/end`. `UnoCSS` shortcuts are `rounded-is` for left side, `rounded-ie` for right side. Example: `rounded-l-5` should be replaced with `rounded-ie-5`.
224+
- If you need to change the border radius for one corner, use `border-start-end-radius` and similar rules. `UnoCSS` shortcuts are `rounded` + top/bottom as either `-bs` (top) or `-be` (bottom) + left/right as either `-is` (left) or `-ie` (right). Example: `rounded-tl-0` should be replaced with `rounded-bs-is-0`.
225+
211226
## Localization (i18n)
212227

213228
npmx.dev uses [@nuxtjs/i18n](https://i18n.nuxtjs.org/) for internationalization. We aim to make the UI accessible to users in their preferred language.
214229

215230
### Approach
216231

217232
- All user-facing strings should use translation keys via `$t()` in templates and script
218-
- Translation files live in `i18n/locales/` (e.g., `en.json`)
219-
- We use the `no_prefix` strategy (no `/en/` or `/fr/` in URLs)
233+
- Translation files live in `i18n/locales/` (e.g., `en-US.json`)
234+
- We use the `no_prefix` strategy (no `/en-US/` or `/fr-FR/` in URLs)
220235
- Locale preference is stored in cookies and respected on subsequent visits
221236

237+
### Adding a new locale
238+
239+
We are using localization using country variants (ISO-6391) via [multiple translation files](https://i18n.nuxtjs.org/docs/guide/lazy-load-translations#multiple-files-lazy-loading) to avoid repeating every key per country.
240+
241+
The [config/i18n.ts](./config/i18n.ts) configuration file will be used to register the new locale:
242+
243+
- `countryLocaleVariants` object will be used to register the country variants
244+
- `locales` object will be used to link the supported locales (country and single one)
245+
- `buildLocales` function will build the target locales
246+
247+
To register a new locale:
248+
249+
- for a single country, your JSON file should include the language and the country in the name (for example, `pl-PL.json`) and register the info at `locales` object
250+
- for multiple country variants, you need to add the default language JSON file (for example for Spanish, `es.json`) and one of the country variants (for example for Spanish for Spain, `es-ES.json`); register the language at `countryLocaleVariants` object adding the country variants with the JSON country file and register the language at `locales` object using the language JSON file (check how we register `es`, `es-ES` and `es-419` in [config/i18n.ts](./config/i18n.ts))
251+
252+
The country file should contain will contain only the translations that differ from the language JSON file, Vue I18n will merge the messages for us.
253+
254+
To add a new locale:
255+
256+
1. Add a new file at [locales](./i18n/locales) folder with the language code as the filename.
257+
2. Copy [en](./i18n/locales/en.json) and translate the strings
258+
3. Add the language to the `locales` array in [config/i18n.ts](./config/i18n.ts), below `en` and `ar`:
259+
- If your language has multiple country variants, add the generic one for language only (only if there are a lot of common entries, you can always add it as a new one)
260+
- Add all country variants in [country variants object](./config/i18n.ts)
261+
- Add all country variants files with empty `messages` object: `{}`
262+
- Translate the strings in the generic language file
263+
- Later, when anyone wants to add the corresponding translations for the country variant, just override any entry in the corresponding file: you can see an example with `es` variants.
264+
- If the generic language already exists:
265+
- If the translation doesn't differ from the generic language, then add the corresponding translations in the corresponding file
266+
- If the translation differs from the generic language, then add the corresponding translations in the corresponding file and remove it from the country variants entry
267+
4. If the language is `right-to-left`, add `dir` option with `rtl` value, for example, for [ar](./config/i18n.ts)
268+
5. If the language requires special pluralization rules, add `pluralRule` callback option, for example, for [ar](./config/i18n.ts)
269+
270+
Check [Pluralization rule callback](https://vue-i18n.intlify.dev/guide/essentials/pluralization.html#custom-pluralization) for more info.
271+
222272
### Adding translations
223273

224-
1. Add your translation key to `i18n/locales/en.json` first (English is the source of truth)
274+
1. Add your translation key to `i18n/locales/en.json` first (American English is the source of truth)
225275
2. Use the key in your component:
226276

227277
```vue
@@ -267,22 +317,6 @@ We recommend the [i18n-ally](https://marketplace.visualstudio.com/items?itemName
267317

268318
The extension is included in our workspace recommendations, so VSCode should prompt you to install it.
269319

270-
### Adding a new locale
271-
272-
1. Create a new JSON file in `i18n/locales/` (e.g., `fr.json`)
273-
2. Add the locale to `nuxt.config.ts`:
274-
275-
```typescript
276-
i18n: {
277-
locales: [
278-
{ code: 'en', language: 'en-US', name: 'English', file: 'en.json' },
279-
{ code: 'fr', language: 'fr-FR', name: 'Francais', file: 'fr.json' },
280-
],
281-
}
282-
```
283-
284-
3. Translate all keys from `en.json`
285-
286320
### Formatting with locale
287321

288322
When formatting numbers or dates that should respect the user's locale, pass the locale:

app/app.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ if (import.meta.client) {
5050

5151
<template>
5252
<div class="min-h-screen flex flex-col bg-bg text-fg">
53-
<a href="#main-content" class="skip-link font-mono">Skip to main content</a>
53+
<a href="#main-content" class="skip-link font-mono">{{ $t('common.skip_link') }}</a>
5454

5555
<AppHeader :show-logo="!isHomepage" />
5656

app/assets/main.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ html {
8080
}
8181
}
8282

83+
html[dir='rtl'] .rtl-flip {
84+
transform: scale(-1, 1);
85+
}
86+
8387
body {
8488
margin: 0;
8589
background-color: var(--bg);

app/components/AccentColorPicker.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const { accentColors, selectedAccentColor, setAccentColor } = useAccentColor()
55
</script>
66

77
<template>
8-
<div role="listbox" aria-label="Accent colors" class="flex items-center gap-4">
8+
<div role="listbox" :aria-label="$t('settings.accent_colors')" class="flex items-center gap-4">
99
<button
1010
v-for="color in accentColors"
1111
:key="color.id"
@@ -19,7 +19,7 @@ const { accentColors, selectedAccentColor, setAccentColor } = useAccentColor()
1919
/>
2020
<button
2121
type="button"
22-
aria-label="Clear accent color"
22+
:aria-label="$t('settings.clear_accent')"
2323
class="size-6 rounded-full transition-transform duration-150 motion-safe:hover:scale-110 focus-ring flex items-center justify-center bg-accent-fallback"
2424
@click="setAccentColor(null)"
2525
>

app/components/AppFooter.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<footer class="border-t border-border mt-auto" aria-label="Site footer">
2+
<footer class="border-t border-border mt-auto">
33
<div class="container py-3 sm:py-8 flex flex-col gap-2 sm:gap-4 text-fg-subtle text-sm">
44
<div class="flex flex-col sm:flex-row items-center justify-between gap-2 sm:gap-4">
55
<p class="font-mono m-0 hidden sm:block">{{ $t('tagline') }}</p>

0 commit comments

Comments
 (0)