@museumwnf/viewer-i18n 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +44 -44
- package/README.md +173 -173
- package/dist/exhibition/ar.json +0 -3
- package/dist/exhibition/cs.json +0 -3
- package/dist/exhibition/de.json +0 -3
- package/dist/exhibition/el.json +0 -3
- package/dist/exhibition/en.json +0 -3
- package/dist/exhibition/es.json +0 -3
- package/dist/exhibition/fr.json +0 -3
- package/dist/exhibition/index.js +0 -33
- package/dist/exhibition/it.json +0 -3
- package/dist/exhibition/pt.json +0 -3
- package/dist/exhibition/se.json +0 -3
- package/dist/exhibition/tr.json +0 -3
- package/dist/gallery/ar.json +0 -3
- package/dist/gallery/cs.json +0 -3
- package/dist/gallery/de.json +0 -3
- package/dist/gallery/el.json +0 -3
- package/dist/gallery/en.json +0 -3
- package/dist/gallery/es.json +0 -3
- package/dist/gallery/fr.json +0 -3
- package/dist/gallery/index.js +0 -33
- package/dist/gallery/it.json +0 -3
- package/dist/gallery/pt.json +0 -3
- package/dist/gallery/se.json +0 -3
- package/dist/gallery/tr.json +0 -3
- package/dist/standalone/ar.json +0 -3
- package/dist/standalone/cs.json +0 -3
- package/dist/standalone/de.json +0 -3
- package/dist/standalone/el.json +0 -3
- package/dist/standalone/en.json +0 -3
- package/dist/standalone/es.json +0 -3
- package/dist/standalone/fr.json +0 -3
- package/dist/standalone/index.js +0 -33
- package/dist/standalone/it.json +0 -3
- package/dist/standalone/pt.json +0 -3
- package/dist/standalone/se.json +0 -3
- package/dist/standalone/tr.json +0 -3
- package/namespaces.json +13 -13
- package/package.json +38 -38
- package/tools/check.mjs +825 -825
package/LICENSE.md
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
This package is Content of the MWNF Website in the sense of the legal notice below, which governs it.
|
|
2
|
-
|
|
3
|
-
Source: https://www.museumwnf.org/about/legal-notice
|
|
4
|
-
Retrieved: 2026-09-08
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Important Legal Notice
|
|
9
|
-
|
|
10
|
-
## DEFINITIONS
|
|
11
|
-
|
|
12
|
-
- **'Museum'**: Refers to Museum Ohne Grenzen e.V. (trading as **'Museum With No Frontiers'**, hereinafter **'MWNF'**), an international non-profit association incorporated under Austrian law, and the Consortium.
|
|
13
|
-
- **'Consortium'**: The group of museums, public/private entities, and individuals coordinated by Museum Ohne Grenzen for the development of the [Website](https://museumwnf.org/).
|
|
14
|
-
- **'Website'**: [museumwnf.org](https://museumwnf.org/) and all associated subdomains and services.
|
|
15
|
-
- **'Content'**: All images, texts, data, software, audio-visual files, and metadata displayed on the Website.
|
|
16
|
-
- **'Orphan Work'**: A work protected by copyright for which the rightsholder cannot be identified or located despite a [reasonably diligent search](https://www.euipo.europa.eu/en/observatory/awareness/ip-in-culture/orphan-works-db).
|
|
17
|
-
|
|
18
|
-
## DISCLAIMER
|
|
19
|
-
|
|
20
|
-
The Website is maintained by MWNF. The European Union funded the initial development of this Website during the realisation of the Discover Islamic Art project. Since EU funding concluded in 2007, the Website has been maintained and further developed solely by MWNF. Content is provided "as is" and constitutes a work in progress. While MWNF makes every effort to ensure accuracy, the Museum is not liable for damages arising from the use of, or reliance on, the Content.
|
|
21
|
-
|
|
22
|
-
## TERMS AND CONDITIONS FOR USE
|
|
23
|
-
|
|
24
|
-
1. **Copyright Protection**: The Content is protected by copyright. MWNF retains all rights unless proprietary rights are held by third parties.
|
|
25
|
-
2. **Permitted Use**: Non-commercial, personal, educational, or scientific use is permitted strictly within the limits of the Austrian Copyright Act (Urheberrechtsgesetz - Urhg) and international treaties.
|
|
26
|
-
3. **Citations and Attribution**: All citations must include either the URL www.museumwnf.org or the specific 'source-URL' published on the relevant page.
|
|
27
|
-
4. **Mandatory Reporting**: Users are required to provide MWNF with a full digital or physical copy of any publication that makes use of Website Content
|
|
28
|
-
5. **Unauthorised Use**: Any reproduction, downloading, printing, or communication to the public of Content from the Website (including text, images, and documentation) for commercial purposes—including commercial publication or personal financial gain—is strictly prohibited without prior written permission from MWNF. Unauthorised use includes, but is not limited to, the redistribution of Content, removing author or source credits, or failing to acknowledge www.museumwnf.org as the source. Furthermore, works identified as belonging to third-party artists or their heirs cannot be copied or downloaded without separate permission from the respective rights holder.
|
|
29
|
-
6. **Enquiries**: Please submit requests or notifications to: [management@museumwnf.net](mailto:management@museumwnf.net).
|
|
30
|
-
7. **Artificial Intelligence & Data Mining (AI Opt-Out)**:
|
|
31
|
-
- **Express Prohibition**: Pursuant to Article 4(3) of Directive (EU) 2019/790 and the corresponding implementation in Austrian law, the Museum expressly reserves all rights regarding Text and Data Mining (TDM) and automated data scraping.
|
|
32
|
-
- **AI Training**: The use of any Content for the training, development, or operation of Artificial Intelligence models, machine learning systems, or Large Language Models (LLMs) is strictly prohibited.
|
|
33
|
-
- **Automated Access**: Unauthorised web scraping, crawling, or automated extraction of data for commercial AI purposes constitutes a breach of these terms.
|
|
34
|
-
8. **Orphan Works**:
|
|
35
|
-
- MWNF displays certain works identified as Orphan Works for cultural and educational purposes, following a diligent search for rightsholders.
|
|
36
|
-
- If you are the rightsholder of a work displayed on this site and wish to assert your rights, please contact MWNF Management.
|
|
37
|
-
|
|
38
|
-
## PRIVACY POLICY
|
|
39
|
-
|
|
40
|
-
Personal data processing is governed by the EU General Data Protection Regulation (GDPR). MWNF undertakes not to sell or rent personal data provided via the Website or newsletter to any third party.
|
|
41
|
-
|
|
42
|
-
## MISCELLANEOUS
|
|
43
|
-
|
|
44
|
-
This Legal Notice is governed by the laws of Austria. Any disputes shall be submitted to the exclusive jurisdiction of the courts of Vienna.
|
|
1
|
+
This package is Content of the MWNF Website in the sense of the legal notice below, which governs it.
|
|
2
|
+
|
|
3
|
+
Source: https://www.museumwnf.org/about/legal-notice
|
|
4
|
+
Retrieved: 2026-09-08
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Important Legal Notice
|
|
9
|
+
|
|
10
|
+
## DEFINITIONS
|
|
11
|
+
|
|
12
|
+
- **'Museum'**: Refers to Museum Ohne Grenzen e.V. (trading as **'Museum With No Frontiers'**, hereinafter **'MWNF'**), an international non-profit association incorporated under Austrian law, and the Consortium.
|
|
13
|
+
- **'Consortium'**: The group of museums, public/private entities, and individuals coordinated by Museum Ohne Grenzen for the development of the [Website](https://museumwnf.org/).
|
|
14
|
+
- **'Website'**: [museumwnf.org](https://museumwnf.org/) and all associated subdomains and services.
|
|
15
|
+
- **'Content'**: All images, texts, data, software, audio-visual files, and metadata displayed on the Website.
|
|
16
|
+
- **'Orphan Work'**: A work protected by copyright for which the rightsholder cannot be identified or located despite a [reasonably diligent search](https://www.euipo.europa.eu/en/observatory/awareness/ip-in-culture/orphan-works-db).
|
|
17
|
+
|
|
18
|
+
## DISCLAIMER
|
|
19
|
+
|
|
20
|
+
The Website is maintained by MWNF. The European Union funded the initial development of this Website during the realisation of the Discover Islamic Art project. Since EU funding concluded in 2007, the Website has been maintained and further developed solely by MWNF. Content is provided "as is" and constitutes a work in progress. While MWNF makes every effort to ensure accuracy, the Museum is not liable for damages arising from the use of, or reliance on, the Content.
|
|
21
|
+
|
|
22
|
+
## TERMS AND CONDITIONS FOR USE
|
|
23
|
+
|
|
24
|
+
1. **Copyright Protection**: The Content is protected by copyright. MWNF retains all rights unless proprietary rights are held by third parties.
|
|
25
|
+
2. **Permitted Use**: Non-commercial, personal, educational, or scientific use is permitted strictly within the limits of the Austrian Copyright Act (Urheberrechtsgesetz - Urhg) and international treaties.
|
|
26
|
+
3. **Citations and Attribution**: All citations must include either the URL www.museumwnf.org or the specific 'source-URL' published on the relevant page.
|
|
27
|
+
4. **Mandatory Reporting**: Users are required to provide MWNF with a full digital or physical copy of any publication that makes use of Website Content
|
|
28
|
+
5. **Unauthorised Use**: Any reproduction, downloading, printing, or communication to the public of Content from the Website (including text, images, and documentation) for commercial purposes—including commercial publication or personal financial gain—is strictly prohibited without prior written permission from MWNF. Unauthorised use includes, but is not limited to, the redistribution of Content, removing author or source credits, or failing to acknowledge www.museumwnf.org as the source. Furthermore, works identified as belonging to third-party artists or their heirs cannot be copied or downloaded without separate permission from the respective rights holder.
|
|
29
|
+
6. **Enquiries**: Please submit requests or notifications to: [management@museumwnf.net](mailto:management@museumwnf.net).
|
|
30
|
+
7. **Artificial Intelligence & Data Mining (AI Opt-Out)**:
|
|
31
|
+
- **Express Prohibition**: Pursuant to Article 4(3) of Directive (EU) 2019/790 and the corresponding implementation in Austrian law, the Museum expressly reserves all rights regarding Text and Data Mining (TDM) and automated data scraping.
|
|
32
|
+
- **AI Training**: The use of any Content for the training, development, or operation of Artificial Intelligence models, machine learning systems, or Large Language Models (LLMs) is strictly prohibited.
|
|
33
|
+
- **Automated Access**: Unauthorised web scraping, crawling, or automated extraction of data for commercial AI purposes constitutes a breach of these terms.
|
|
34
|
+
8. **Orphan Works**:
|
|
35
|
+
- MWNF displays certain works identified as Orphan Works for cultural and educational purposes, following a diligent search for rightsholders.
|
|
36
|
+
- If you are the rightsholder of a work displayed on this site and wish to assert your rights, please contact MWNF Management.
|
|
37
|
+
|
|
38
|
+
## PRIVACY POLICY
|
|
39
|
+
|
|
40
|
+
Personal data processing is governed by the EU General Data Protection Regulation (GDPR). MWNF undertakes not to sell or rent personal data provided via the Website or newsletter to any third party.
|
|
41
|
+
|
|
42
|
+
## MISCELLANEOUS
|
|
43
|
+
|
|
44
|
+
This Legal Notice is governed by the laws of Austria. Any disputes shall be submitted to the exclusive jurisdiction of the courts of Vienna.
|
package/README.md
CHANGED
|
@@ -1,173 +1,173 @@
|
|
|
1
|
-
# viewer-i18n
|
|
2
|
-
|
|
3
|
-
The texts shared by the MWNF websites: menu labels, buttons, the labels of an
|
|
4
|
-
item sheet, and the editorial blocks that are the same on every website of a
|
|
5
|
-
kind. A text that belongs to **one** website is not here — it lives in that
|
|
6
|
-
website's own `locales/` folder.
|
|
7
|
-
|
|
8
|
-
The museum content itself — the objects, the exhibitions, the partners — is not
|
|
9
|
-
here either. It arrives already translated with each website's data.
|
|
10
|
-
|
|
11
|
-
## Editing a text
|
|
12
|
-
|
|
13
|
-
You need a GitHub account and a browser; nothing else.
|
|
14
|
-
|
|
15
|
-
1. **Open the folder for the section you want** — `core/`, `layout/`,
|
|
16
|
-
`gallery/` or `exhibition/` — and click the file for your language.
|
|
17
|
-
`en.json` is English, `fr.json` French, and so on.
|
|
18
|
-
2. **Click the pencil** (✏️, top right). Change only the text between the
|
|
19
|
-
second pair of quotation marks on a line. The part before the colon is the
|
|
20
|
-
name of the entry and must stay exactly as it is.
|
|
21
|
-
3. **Click "Commit changes…", then "Propose changes".**
|
|
22
|
-
4. **Wait for the automatic check.** After a minute or two the page shows a
|
|
23
|
-
green tick and the change is merged by itself. If something is off, a
|
|
24
|
-
comment appears explaining in plain language what to fix; edit again on the
|
|
25
|
-
same page and the check runs afresh.
|
|
26
|
-
|
|
27
|
-
The websites pick the change up at their next platform update.
|
|
28
|
-
|
|
29
|
-
## Starting a new language
|
|
30
|
-
|
|
31
|
-
Open `en.json` in a section, copy all of it, then **Add file → Create new
|
|
32
|
-
file**, name it with the two-letter code (`ar.json`, `es.json`, `fr.json`, …),
|
|
33
|
-
paste, and translate. Do the same in each section the language needs.
|
|
34
|
-
|
|
35
|
-
A language does not have to be complete: any text you have not translated yet
|
|
36
|
-
shows in English. There is nothing to declare anywhere and no code to change.
|
|
37
|
-
|
|
38
|
-
## What a text may contain
|
|
39
|
-
|
|
40
|
-
A text is **just text**. It may be formatted with Markdown — `**bold**`,
|
|
41
|
-
`*italic*`, `[a link](https://example.org)`, blank lines between paragraphs —
|
|
42
|
-
and that is all.
|
|
43
|
-
|
|
44
|
-
It may not contain `{` or `}`. Nothing is ever inserted into a text: a number,
|
|
45
|
-
a date or a name is placed next to the text by the website, never inside it.
|
|
46
|
-
This is why a text can be translated freely, without having to preserve
|
|
47
|
-
anything.
|
|
48
|
-
|
|
49
|
-
Writing an HTML tag is not forbidden, because it does not work: the websites
|
|
50
|
-
escape HTML instead of rendering it, so `<b>Home</b>` appears on the page as
|
|
51
|
-
those exact characters, angle brackets and all. Use Markdown.
|
|
52
|
-
|
|
53
|
-
## The sections
|
|
54
|
-
|
|
55
|
-
| Folder | Holds the texts of |
|
|
56
|
-
| --- | --- |
|
|
57
|
-
| `core/` | the pages every website builds on |
|
|
58
|
-
| `layout/` | the frame around a page: navigation, language chooser, footer |
|
|
59
|
-
| `gallery/` | the galleries (Carpets, Amulets, …) |
|
|
60
|
-
| `catalogue/` | the list pages every website has: the filters, the search form, the results and their pages |
|
|
61
|
-
| `sheet/` | the labels of a record's sheet — name, date, dimensions, provenance, who prepared it |
|
|
62
|
-
| `record/` | what surrounds the sheet: back, timeline, related items, credits, citation, the glossary, the dynasties popout |
|
|
63
|
-
| `exhibition/` | the exhibitions (Water in Islam, The Use of Colours in Art, …) |
|
|
64
|
-
| `timeline/` | the timeline pages: the country and period form, the results, the errors — worded so the same text serves a gallery, an exhibition or a standalone site |
|
|
65
|
-
| `partner/` | the partner pages: the profile fields, the map, the list and its sorting, "not found" — worded the same way |
|
|
66
|
-
|
|
67
|
-
`gallery/` and `exhibition/` hold only what a gallery or an exhibition says and no other kind of website does — the sections, the navigation, the partner page's intro, the timeline page's intro, the notices, the themes. What every website says the same way lives once, in `catalogue/`, `sheet/`, `record/`, `timeline/` and `partner/`, so that the seven websites read one vocabulary rather than seven; since 2.0.0 the two family sections carry no copy of it. `timeline/` and `partner/` carry no product name: they say "in this site", never "Gallery" or "Exhibition", so the one text serves every kind of website — the few entries whose wording is a product's own stay in `gallery` and `exhibition`.
|
|
68
|
-
|
|
69
|
-
Entry names are written as `section.group.name` — three parts, so
|
|
70
|
-
`gallery.sheet.inventoryNumber` reads as "in the galleries, on the item sheet,
|
|
71
|
-
the inventory number", and `sheet.field.inventoryNumber` "on any sheet, the
|
|
72
|
-
field, the inventory number".
|
|
73
|
-
|
|
74
|
-
A shared label carries no trailing colon: whether a label ends in a colon is a
|
|
75
|
-
matter of layout, which the page decides.
|
|
76
|
-
|
|
77
|
-
## Which languages a section must exist in
|
|
78
|
-
|
|
79
|
-
A website offers the languages its data package declares, and a visitor who
|
|
80
|
-
picks one reads the whole page in it — the records from the package, the
|
|
81
|
-
texts from here. So each kind of website names, in `namespaces.json` under
|
|
82
|
-
`languages`, the languages its websites offer, and **every section that kind
|
|
83
|
-
receives has to be complete in each of them**. The shared sections are in
|
|
84
|
-
every bundle, so they need the union: today `ar cs de el en es fr it pt se tr`.
|
|
85
|
-
The automatic check refuses a section that is missing a language, or an entry
|
|
86
|
-
in one, that a website of that kind offers.
|
|
87
|
-
|
|
88
|
-
To add a language a website is about to offer: add it to the kind's list,
|
|
89
|
-
then create the file in every section that kind receives. [`sources.md`](sources.md)
|
|
90
|
-
says where the existing translations came from.
|
|
91
|
-
|
|
92
|
-
`se` is Swedish: the data packages declare it with the legacy code, and the
|
|
93
|
-
websites match codes as written, so the file is named after what they say.
|
|
94
|
-
|
|
95
|
-
## For developers
|
|
96
|
-
|
|
97
|
-
Each kind of website receives one prebuilt bundle, and nothing else:
|
|
98
|
-
|
|
99
|
-
| Kind | Bundle | Contains |
|
|
100
|
-
| --- | --- | --- |
|
|
101
|
-
| Products (Islamic Art, Baroque Art, Sharing History) | `@museumwnf/viewer-i18n/standalone` | `core` + `layout` + `catalogue` + `sheet` + `record` + `exhibition` + `timeline` + `partner` |
|
|
102
|
-
| Galleries | `@museumwnf/viewer-i18n/gallery` | the same, with `gallery` in place of `exhibition` |
|
|
103
|
-
| Exhibitions | `@museumwnf/viewer-i18n/exhibition` | the same as Products |
|
|
104
|
-
|
|
105
|
-
```js
|
|
106
|
-
import { catalogues } from '@museumwnf/viewer-i18n/gallery'
|
|
107
|
-
// { en: { 'core.nav.home': 'Home', … } }
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
A website merges its own `locales/<lang>.json` over that bundle, and the local
|
|
111
|
-
value wins. That is the only merge rule in the system: a website may overload
|
|
112
|
-
any entry it receives and add entries of its own, but it cannot delete one.
|
|
113
|
-
|
|
114
|
-
It says which bundle it receives, and what its own entries are called, in its
|
|
115
|
-
`package.json`:
|
|
116
|
-
|
|
117
|
-
```json
|
|
118
|
-
"viewerI18n": { "class": "gallery", "namespace": "carpets" }
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
`class` is one of `standalone`, `gallery`, `exhibition`. `namespace` is one
|
|
122
|
-
lowercase word, no hyphens (`carpets`, `waterInIslam`) — it cannot be one of
|
|
123
|
-
the shared section names, and it is the prefix the website's own entries carry.
|
|
124
|
-
The checks below read this to know what a file may contain, so they refuse to
|
|
125
|
-
run without it.
|
|
126
|
-
|
|
127
|
-
`namespaces.json` is the registry: the sections that exist and what each bundle
|
|
128
|
-
contains. `tools/build.mjs` produces the bundles; `tools/check.mjs` is the
|
|
129
|
-
whole rulebook, and also ships with the package so websites enforce the same
|
|
130
|
-
rules on their own texts:
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
npx viewer-i18n-check --site . # a website's locales/, on its own
|
|
134
|
-
npx viewer-i18n-check --app . # …and every entry its code asks for
|
|
135
|
-
npx viewer-i18n-check --app . --languages ar,en,fr # …for a set other than the package's
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
`--app` reads a name wherever the website asks for one: a `t('…')` or `$t('…')`
|
|
139
|
-
call, an `I18nText` keypath, and — since 2.1.0 — a name written in a spec the
|
|
140
|
-
platform renders, such as `title: 'carpets.identity.title'` in a
|
|
141
|
-
`dataset.config.js` or a label in a catalogue or sheet spec for viewer-layout's
|
|
142
|
-
composed views. A plain string reads as a name when it has three parts and its
|
|
143
|
-
first is a section the website receives; every name found has to exist.
|
|
144
|
-
|
|
145
|
-
`--app` also reads the languages the website offers — `manifest.site.languages`
|
|
146
|
-
of the installed `@museumwnf/<dataset>-data`, the list the website itself reads —
|
|
147
|
-
and fails when the installed bundle has no complete file for one of them: that
|
|
148
|
-
visitor would read the records in their language and every label in English.
|
|
149
|
-
`--languages` asks about another set, for a website about to offer one.
|
|
150
|
-
|
|
151
|
-
## Licence
|
|
152
|
-
|
|
153
|
-
This package is Content of the MWNF Website under the [MWNF legal
|
|
154
|
-
notice](https://www.museumwnf.org/about/legal-notice), which governs its use
|
|
155
|
-
(non-commercial, personal, educational and scientific use is permitted, with
|
|
156
|
-
attribution and mandatory reporting — see the notice for the full terms). The
|
|
157
|
-
notice text also ships in this package as `LICENSE.md`. This package carries
|
|
158
|
-
translated data (the dictionary), not just code, so the notice governs the
|
|
159
|
-
texts as much as it governs the data packages.
|
|
160
|
-
|
|
161
|
-
## Release procedure
|
|
162
|
-
|
|
163
|
-
1. Merge to `main` via a pull request (CI validates the texts and builds every
|
|
164
|
-
website against the packed tarball).
|
|
165
|
-
2. Create a GitHub release tagged `vX.Y.Z` — CI publishes to npmjs (versions up
|
|
166
|
-
to 3.0.1, published as `@metanull/viewer-i18n`, remain available on GitHub
|
|
167
|
-
Packages, frozen; no new version is published there).
|
|
168
|
-
3. Semver: **patch** = a text changed; **minor** = an entry or a language
|
|
169
|
-
added; **major** = an entry renamed or removed.
|
|
170
|
-
|
|
171
|
-
Websites receive it through the platform's propagation run — see
|
|
172
|
-
[MAINTENANCE.md](https://github.com/
|
|
173
|
-
in `viewer-workflows`.
|
|
1
|
+
# viewer-i18n
|
|
2
|
+
|
|
3
|
+
The texts shared by the MWNF websites: menu labels, buttons, the labels of an
|
|
4
|
+
item sheet, and the editorial blocks that are the same on every website of a
|
|
5
|
+
kind. A text that belongs to **one** website is not here — it lives in that
|
|
6
|
+
website's own `locales/` folder.
|
|
7
|
+
|
|
8
|
+
The museum content itself — the objects, the exhibitions, the partners — is not
|
|
9
|
+
here either. It arrives already translated with each website's data.
|
|
10
|
+
|
|
11
|
+
## Editing a text
|
|
12
|
+
|
|
13
|
+
You need a GitHub account and a browser; nothing else.
|
|
14
|
+
|
|
15
|
+
1. **Open the folder for the section you want** — `core/`, `layout/`,
|
|
16
|
+
`gallery/` or `exhibition/` — and click the file for your language.
|
|
17
|
+
`en.json` is English, `fr.json` French, and so on.
|
|
18
|
+
2. **Click the pencil** (✏️, top right). Change only the text between the
|
|
19
|
+
second pair of quotation marks on a line. The part before the colon is the
|
|
20
|
+
name of the entry and must stay exactly as it is.
|
|
21
|
+
3. **Click "Commit changes…", then "Propose changes".**
|
|
22
|
+
4. **Wait for the automatic check.** After a minute or two the page shows a
|
|
23
|
+
green tick and the change is merged by itself. If something is off, a
|
|
24
|
+
comment appears explaining in plain language what to fix; edit again on the
|
|
25
|
+
same page and the check runs afresh.
|
|
26
|
+
|
|
27
|
+
The websites pick the change up at their next platform update.
|
|
28
|
+
|
|
29
|
+
## Starting a new language
|
|
30
|
+
|
|
31
|
+
Open `en.json` in a section, copy all of it, then **Add file → Create new
|
|
32
|
+
file**, name it with the two-letter code (`ar.json`, `es.json`, `fr.json`, …),
|
|
33
|
+
paste, and translate. Do the same in each section the language needs.
|
|
34
|
+
|
|
35
|
+
A language does not have to be complete: any text you have not translated yet
|
|
36
|
+
shows in English. There is nothing to declare anywhere and no code to change.
|
|
37
|
+
|
|
38
|
+
## What a text may contain
|
|
39
|
+
|
|
40
|
+
A text is **just text**. It may be formatted with Markdown — `**bold**`,
|
|
41
|
+
`*italic*`, `[a link](https://example.org)`, blank lines between paragraphs —
|
|
42
|
+
and that is all.
|
|
43
|
+
|
|
44
|
+
It may not contain `{` or `}`. Nothing is ever inserted into a text: a number,
|
|
45
|
+
a date or a name is placed next to the text by the website, never inside it.
|
|
46
|
+
This is why a text can be translated freely, without having to preserve
|
|
47
|
+
anything.
|
|
48
|
+
|
|
49
|
+
Writing an HTML tag is not forbidden, because it does not work: the websites
|
|
50
|
+
escape HTML instead of rendering it, so `<b>Home</b>` appears on the page as
|
|
51
|
+
those exact characters, angle brackets and all. Use Markdown.
|
|
52
|
+
|
|
53
|
+
## The sections
|
|
54
|
+
|
|
55
|
+
| Folder | Holds the texts of |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `core/` | the pages every website builds on |
|
|
58
|
+
| `layout/` | the frame around a page: navigation, language chooser, footer |
|
|
59
|
+
| `gallery/` | the galleries (Carpets, Amulets, …) |
|
|
60
|
+
| `catalogue/` | the list pages every website has: the filters, the search form, the results and their pages |
|
|
61
|
+
| `sheet/` | the labels of a record's sheet — name, date, dimensions, provenance, who prepared it |
|
|
62
|
+
| `record/` | what surrounds the sheet: back, timeline, related items, credits, citation, the glossary, the dynasties popout |
|
|
63
|
+
| `exhibition/` | the exhibitions (Water in Islam, The Use of Colours in Art, …) |
|
|
64
|
+
| `timeline/` | the timeline pages: the country and period form, the results, the errors — worded so the same text serves a gallery, an exhibition or a standalone site |
|
|
65
|
+
| `partner/` | the partner pages: the profile fields, the map, the list and its sorting, "not found" — worded the same way |
|
|
66
|
+
|
|
67
|
+
`gallery/` and `exhibition/` hold only what a gallery or an exhibition says and no other kind of website does — the sections, the navigation, the partner page's intro, the timeline page's intro, the notices, the themes. What every website says the same way lives once, in `catalogue/`, `sheet/`, `record/`, `timeline/` and `partner/`, so that the seven websites read one vocabulary rather than seven; since 2.0.0 the two family sections carry no copy of it. `timeline/` and `partner/` carry no product name: they say "in this site", never "Gallery" or "Exhibition", so the one text serves every kind of website — the few entries whose wording is a product's own stay in `gallery` and `exhibition`.
|
|
68
|
+
|
|
69
|
+
Entry names are written as `section.group.name` — three parts, so
|
|
70
|
+
`gallery.sheet.inventoryNumber` reads as "in the galleries, on the item sheet,
|
|
71
|
+
the inventory number", and `sheet.field.inventoryNumber` "on any sheet, the
|
|
72
|
+
field, the inventory number".
|
|
73
|
+
|
|
74
|
+
A shared label carries no trailing colon: whether a label ends in a colon is a
|
|
75
|
+
matter of layout, which the page decides.
|
|
76
|
+
|
|
77
|
+
## Which languages a section must exist in
|
|
78
|
+
|
|
79
|
+
A website offers the languages its data package declares, and a visitor who
|
|
80
|
+
picks one reads the whole page in it — the records from the package, the
|
|
81
|
+
texts from here. So each kind of website names, in `namespaces.json` under
|
|
82
|
+
`languages`, the languages its websites offer, and **every section that kind
|
|
83
|
+
receives has to be complete in each of them**. The shared sections are in
|
|
84
|
+
every bundle, so they need the union: today `ar cs de el en es fr it pt se tr`.
|
|
85
|
+
The automatic check refuses a section that is missing a language, or an entry
|
|
86
|
+
in one, that a website of that kind offers.
|
|
87
|
+
|
|
88
|
+
To add a language a website is about to offer: add it to the kind's list,
|
|
89
|
+
then create the file in every section that kind receives. [`sources.md`](sources.md)
|
|
90
|
+
says where the existing translations came from.
|
|
91
|
+
|
|
92
|
+
`se` is Swedish: the data packages declare it with the legacy code, and the
|
|
93
|
+
websites match codes as written, so the file is named after what they say.
|
|
94
|
+
|
|
95
|
+
## For developers
|
|
96
|
+
|
|
97
|
+
Each kind of website receives one prebuilt bundle, and nothing else:
|
|
98
|
+
|
|
99
|
+
| Kind | Bundle | Contains |
|
|
100
|
+
| --- | --- | --- |
|
|
101
|
+
| Products (Islamic Art, Baroque Art, Sharing History) | `@museumwnf/viewer-i18n/standalone` | `core` + `layout` + `catalogue` + `sheet` + `record` + `exhibition` + `timeline` + `partner` |
|
|
102
|
+
| Galleries | `@museumwnf/viewer-i18n/gallery` | the same, with `gallery` in place of `exhibition` |
|
|
103
|
+
| Exhibitions | `@museumwnf/viewer-i18n/exhibition` | the same as Products |
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
import { catalogues } from '@museumwnf/viewer-i18n/gallery'
|
|
107
|
+
// { en: { 'core.nav.home': 'Home', … } }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
A website merges its own `locales/<lang>.json` over that bundle, and the local
|
|
111
|
+
value wins. That is the only merge rule in the system: a website may overload
|
|
112
|
+
any entry it receives and add entries of its own, but it cannot delete one.
|
|
113
|
+
|
|
114
|
+
It says which bundle it receives, and what its own entries are called, in its
|
|
115
|
+
`package.json`:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
"viewerI18n": { "class": "gallery", "namespace": "carpets" }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`class` is one of `standalone`, `gallery`, `exhibition`. `namespace` is one
|
|
122
|
+
lowercase word, no hyphens (`carpets`, `waterInIslam`) — it cannot be one of
|
|
123
|
+
the shared section names, and it is the prefix the website's own entries carry.
|
|
124
|
+
The checks below read this to know what a file may contain, so they refuse to
|
|
125
|
+
run without it.
|
|
126
|
+
|
|
127
|
+
`namespaces.json` is the registry: the sections that exist and what each bundle
|
|
128
|
+
contains. `tools/build.mjs` produces the bundles; `tools/check.mjs` is the
|
|
129
|
+
whole rulebook, and also ships with the package so websites enforce the same
|
|
130
|
+
rules on their own texts:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx viewer-i18n-check --site . # a website's locales/, on its own
|
|
134
|
+
npx viewer-i18n-check --app . # …and every entry its code asks for
|
|
135
|
+
npx viewer-i18n-check --app . --languages ar,en,fr # …for a set other than the package's
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`--app` reads a name wherever the website asks for one: a `t('…')` or `$t('…')`
|
|
139
|
+
call, an `I18nText` keypath, and — since 2.1.0 — a name written in a spec the
|
|
140
|
+
platform renders, such as `title: 'carpets.identity.title'` in a
|
|
141
|
+
`dataset.config.js` or a label in a catalogue or sheet spec for viewer-layout's
|
|
142
|
+
composed views. A plain string reads as a name when it has three parts and its
|
|
143
|
+
first is a section the website receives; every name found has to exist.
|
|
144
|
+
|
|
145
|
+
`--app` also reads the languages the website offers — `manifest.site.languages`
|
|
146
|
+
of the installed `@museumwnf/<dataset>-data`, the list the website itself reads —
|
|
147
|
+
and fails when the installed bundle has no complete file for one of them: that
|
|
148
|
+
visitor would read the records in their language and every label in English.
|
|
149
|
+
`--languages` asks about another set, for a website about to offer one.
|
|
150
|
+
|
|
151
|
+
## Licence
|
|
152
|
+
|
|
153
|
+
This package is Content of the MWNF Website under the [MWNF legal
|
|
154
|
+
notice](https://www.museumwnf.org/about/legal-notice), which governs its use
|
|
155
|
+
(non-commercial, personal, educational and scientific use is permitted, with
|
|
156
|
+
attribution and mandatory reporting — see the notice for the full terms). The
|
|
157
|
+
notice text also ships in this package as `LICENSE.md`. This package carries
|
|
158
|
+
translated data (the dictionary), not just code, so the notice governs the
|
|
159
|
+
texts as much as it governs the data packages.
|
|
160
|
+
|
|
161
|
+
## Release procedure
|
|
162
|
+
|
|
163
|
+
1. Merge to `main` via a pull request (CI validates the texts and builds every
|
|
164
|
+
website against the packed tarball).
|
|
165
|
+
2. Create a GitHub release tagged `vX.Y.Z` — CI publishes to npmjs (versions up
|
|
166
|
+
to 3.0.1, published as `@metanull/viewer-i18n`, remain available on GitHub
|
|
167
|
+
Packages, frozen; no new version is published there).
|
|
168
|
+
3. Semver: **patch** = a text changed; **minor** = an entry or a language
|
|
169
|
+
added; **major** = an entry renamed or removed.
|
|
170
|
+
|
|
171
|
+
Websites receive it through the platform's propagation run — see
|
|
172
|
+
[MAINTENANCE.md](https://github.com/museumwithnofrontiers/viewer-workflows/blob/main/MAINTENANCE.md)
|
|
173
|
+
in `viewer-workflows`.
|
package/dist/exhibition/ar.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "التالي",
|
|
89
89
|
"core.pagination.previous": "السابق",
|
|
90
90
|
"core.project.baroqueArt": "اكتشف فن الباروك",
|
|
91
|
-
"core.project.carpetArt": "اكتشف فن السجاد",
|
|
92
91
|
"core.project.explorePartners": "اكتشف مجموعات الفن الإسلامي",
|
|
93
92
|
"core.project.galleries": "معارض متحف بلا حدود",
|
|
94
|
-
"core.project.glassArt": "اكتشف فن الزجاج",
|
|
95
93
|
"core.project.islamicArt": "اكتشف الفن الإسلامي",
|
|
96
94
|
"core.project.sharingHistory": "تاريخ مشترك",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "جارٍ التحميل…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/cs.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Další",
|
|
89
89
|
"core.pagination.previous": "Předchozí",
|
|
90
90
|
"core.project.baroqueArt": "Discover Baroque Art",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Objevte sbírky islámského umění",
|
|
93
92
|
"core.project.galleries": "Galerie MWNF",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Discover Islamic Art",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Načítání…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/de.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Weiter",
|
|
89
89
|
"core.pagination.previous": "Zurück",
|
|
90
90
|
"core.project.baroqueArt": "Discover Baroque Art",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Islamische Kunstsammlungen entdecken",
|
|
93
92
|
"core.project.galleries": "MWNF-Galerien",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Discover Islamic Art",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Wird geladen…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/el.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Επόμενη",
|
|
89
89
|
"core.pagination.previous": "Προηγούμενη",
|
|
90
90
|
"core.project.baroqueArt": "Discover Baroque Art",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Εξερευνήστε τις συλλογές ισλαμικής τέχνης",
|
|
93
92
|
"core.project.galleries": "Γκαλερί MWNF",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Discover Islamic Art",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Φόρτωση…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/en.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Next",
|
|
89
89
|
"core.pagination.previous": "Previous",
|
|
90
90
|
"core.project.baroqueArt": "Discover Baroque Art",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Explore Islamic Art Collections",
|
|
93
92
|
"core.project.galleries": "MWNF Galleries",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Discover Islamic Art",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Loading…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/es.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Siguiente",
|
|
89
89
|
"core.pagination.previous": "Anterior",
|
|
90
90
|
"core.project.baroqueArt": "Discover Baroque Art",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Explore las colecciones de arte islámico",
|
|
93
92
|
"core.project.galleries": "Galerías MWNF",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Descubrir el Arte Islámico",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Cargando…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|
package/dist/exhibition/fr.json
CHANGED
|
@@ -88,13 +88,10 @@
|
|
|
88
88
|
"core.pagination.next": "Suivant",
|
|
89
89
|
"core.pagination.previous": "Précédent",
|
|
90
90
|
"core.project.baroqueArt": "Découvrir l’Art Baroque",
|
|
91
|
-
"core.project.carpetArt": "Discover Carpet Art",
|
|
92
91
|
"core.project.explorePartners": "Explorez les collections d’art islamique",
|
|
93
92
|
"core.project.galleries": "Galeries MWNF",
|
|
94
|
-
"core.project.glassArt": "Discover Glass Art",
|
|
95
93
|
"core.project.islamicArt": "Découvrir l’art islamique",
|
|
96
94
|
"core.project.sharingHistory": "Sharing History",
|
|
97
|
-
"core.project.tableIsSet": "The Table is Set",
|
|
98
95
|
"core.status.loading": "Chargement…",
|
|
99
96
|
"exhibition.action.enter": "Enter",
|
|
100
97
|
"exhibition.action.here": "here",
|