mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-24 05:05:20 -04:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
8437c47bf7
@ -36,8 +36,11 @@ home:
|
|||||||
button: 'Zeige den Generator'
|
button: 'Zeige den Generator'
|
||||||
header2: 'Generiere einen Link'
|
header2: 'Generiere einen Link'
|
||||||
base: 'Ausgehend von'
|
base: 'Ausgehend von'
|
||||||
alt: 'Du kannst auch austauschbare Formen in jedes Feld eintragen, z.B. <code>er&sie</code> = „er“ or „sie“.'
|
alt: 'Du kannst auch austauschbare Formen in jedes Feld eintragen, z.B. <code>er&sie</code> = „er“ oder „sie“.'
|
||||||
pronunciation: 'Du kannst auch die Aussprache spezifizieren, die indem du nach einem senkrechten Strich „|“ (mit der Tastenkombination [Alt Gr] und [<>] ) hinzufügst. Benutze dafür die Lautschrift IPA (Internationales Phonetisches Alphabet). Ein Beispiel wäre: <code>sier|siˑʁ</code> = „sier“, ausgesprochen wie /siˑʁ/.'
|
pronunciation: >
|
||||||
|
Du kannst auch die Aussprache spezifizieren, die indem du nach einem senkrechten Strich „|“ (mit der Tastenkombination <kbd>Alt Gr+<</kbd>) hinzufügst.
|
||||||
|
Benutze dafür die {https://de.wikipedia.org/wiki/Liste_der_IPA-Zeichen=Lautschrift IPA (Internationales Phonetisches Alphabet)}.
|
||||||
|
Ein Beispiel wäre: <code>sier|zi:ɐ̯</code> = „sier“, ausgesprochen wie /zi:ɐ̯/.
|
||||||
whatisit: 'Was ist das Problem mit Pronomen?'
|
whatisit: 'Was ist das Problem mit Pronomen?'
|
||||||
mission:
|
mission:
|
||||||
header: 'Unsere Mission'
|
header: 'Unsere Mission'
|
||||||
@ -246,10 +249,10 @@ faq:
|
|||||||
Online ist es noch einfacher: Füge einfach deine Pronomen (oder einen Link zu Beispielen von unserer Website) zu deiner „Bio“ hinzu.
|
Online ist es noch einfacher: Füge einfach deine Pronomen (oder einen Link zu Beispielen von unserer Website) zu deiner „Bio“ hinzu.
|
||||||
- >
|
- >
|
||||||
Denke auch daran, dass manche Menschen je nach Situation einen anderen Namen und andere Pronomen verwenden könnten.
|
Denke auch daran, dass manche Menschen je nach Situation einen anderen Namen und andere Pronomen verwenden könnten.
|
||||||
Sie hatten vielleicht vor manchen Freund*innen oder Arbeitskolleg*innen noch kein Coming Out, aber bei anderen Freund*innen fühlen sie sich wohl und gehen damit offen um.
|
Sie hatten vielleicht vor manchen Freund*innen oder Arbeitskolleg*innen noch kein Coming-out, aber bei anderen Freund*innen fühlen sie sich wohl und gehen damit offen um.
|
||||||
Sei rücksichtsvoll. Du kannst zum Beispiel fragen: „Welche Pronomen soll ich vor deiner*m Chef*in benutzen?“, etc.
|
Sei rücksichtsvoll. Du kannst zum Beispiel fragen: „Welche Pronomen soll ich vor deiner*m Chef*in benutzen?“, etc.
|
||||||
- >
|
- >
|
||||||
Manche Menschen geben mehrere Pronomen an, z.B. „{/er&sie=er/sie}“ oder „{/sier&er=sier/er}“.
|
Manche Menschen geben mehrere Pronomen an, z.B. „{/er&sie=er oder sie}“ oder auch „{/sier&er=sier oder er}“.
|
||||||
Das bedeutet, dass sie alle diese Formen mögen. Normalerweise ist die erste die bevorzugte.
|
Das bedeutet, dass sie alle diese Formen mögen. Normalerweise ist die erste die bevorzugte.
|
||||||
who-uses-it:
|
who-uses-it:
|
||||||
question: 'Benutzt das überhaupt irgendwer?'
|
question: 'Benutzt das überhaupt irgendwer?'
|
||||||
@ -386,7 +389,7 @@ contact:
|
|||||||
language: >
|
language: >
|
||||||
Wir sind ein internationales Team - die Personen, die eine bestimmte Sprachversion erstellt haben, sind
|
Wir sind ein internationales Team - die Personen, die eine bestimmte Sprachversion erstellt haben, sind
|
||||||
möglicherweise nicht dieselben, die deine Nachricht lesen werden. Daher würden wir es begrüßen, wenn du uns in
|
möglicherweise nicht dieselben, die deine Nachricht lesen werden. Daher würden wir es begrüßen, wenn du uns in
|
||||||
<strong>Englisch or Polnisch</strong> kontaktierst.
|
<strong>Englisch oder Polnisch</strong> kontaktierst.
|
||||||
team:
|
team:
|
||||||
name: 'Das „Rat für neutrale Sprache“ Kollektiv'
|
name: 'Das „Rat für neutrale Sprache“ Kollektiv'
|
||||||
nameShort: 'Kollektiv'
|
nameShort: 'Kollektiv'
|
||||||
@ -569,7 +572,7 @@ profile:
|
|||||||
names: 'Namen'
|
names: 'Namen'
|
||||||
pronouns: 'Pronomen'
|
pronouns: 'Pronomen'
|
||||||
pronounsInfo: >
|
pronounsInfo: >
|
||||||
Du kannst entweder ein <strong>Pronomen</strong> (z.B. „sier“ or „sie/ihr“) oder einen <strong>Link</strong> (z.B. „https://de.pronouns.page/dey“)
|
Du kannst entweder ein <strong>Pronomen</strong> (z.B. „sier“ oder „sie/ihr“) oder einen <strong>Link</strong> (z.B. „https://de.pronouns.page/dey“)
|
||||||
oder <strong>vier benutzerdefinierten Formen</strong> (z.B. „xier/xies/xiem/xien“).
|
oder <strong>vier benutzerdefinierten Formen</strong> (z.B. „xier/xies/xiem/xien“).
|
||||||
Du kannst auch den {/pronomen#generator=<strong>Generator</strong>} verwenden, um die Sätze mit benutzerdefinierten Formen auszufüllen.
|
Du kannst auch den {/pronomen#generator=<strong>Generator</strong>} verwenden, um die Sätze mit benutzerdefinierten Formen auszufüllen.
|
||||||
pronounsNotFound: 'Nicht erkennbares Format. Bitte beachte die oben genannte Anweisung.'
|
pronounsNotFound: 'Nicht erkennbares Format. Bitte beachte die oben genannte Anweisung.'
|
||||||
@ -673,7 +676,7 @@ profile:
|
|||||||
relationship: 'Verhältnis (z.B. „Partner*in“, „beste*r Freund*in“)'
|
relationship: 'Verhältnis (z.B. „Partner*in“, „beste*r Freund*in“)'
|
||||||
mutual: 'Diese Verbindung besteht in beide Richtungen'
|
mutual: 'Diese Verbindung besteht in beide Richtungen'
|
||||||
yourMentions:
|
yourMentions:
|
||||||
header: 'Mein Umfeld Erwähnungen '
|
header: 'Erwähnungen aus deinem Umfeld'
|
||||||
description: >
|
description: >
|
||||||
Hier ist die Liste der Personen, die dich zu ihrem Umfeld hinzugefügt haben. Wenn du sie auch zu deinem
|
Hier ist die Liste der Personen, die dich zu ihrem Umfeld hinzugefügt haben. Wenn du sie auch zu deinem
|
||||||
Umfeld hinzufügst, wird auf beiden Karten ein Häkchen [s:shield-check] angezeigt.
|
Umfeld hinzufügst, wird auf beiden Karten ein Häkchen [s:shield-check] angezeigt.
|
||||||
@ -739,6 +742,43 @@ profile:
|
|||||||
success: 'Deine Visitenkarten wurden erfolgreich wiederhergestellt! Die Seite wird nun neugeladen.'
|
success: 'Deine Visitenkarten wurden erfolgreich wiederhergestellt! Die Seite wird nun neugeladen.'
|
||||||
error:
|
error:
|
||||||
signature: 'Ungültige Signatur, kann die Integrität der Sicherungsdatei nicht verifizieren'
|
signature: 'Ungültige Signatur, kann die Integrität der Sicherungsdatei nicht verifizieren'
|
||||||
|
markdown:
|
||||||
|
enable: 'Verwende Formattierung mit Markdown in deiner Visitenkarte'
|
||||||
|
features: 'Zeige unterstützte Markdownsyntax'
|
||||||
|
examples:
|
||||||
|
- 'ein **fettgedruckter** Text'
|
||||||
|
- 'ein _kursiver_ Text'
|
||||||
|
- 'ein `Code`-Fragment'
|
||||||
|
- 'ein ~~durchgestrichener~~ Text'
|
||||||
|
- 'ein ==markierter== Text'
|
||||||
|
- 'ein ^hochgestellter^ Text'
|
||||||
|
- 'ein ~tiefgestellter~ Text'
|
||||||
|
- >
|
||||||
|
benutze einen umgedrehten Schrägstrich `\`, um \_Formatierungszeichen\_ \*\*abzuschalten\*\*,
|
||||||
|
insbesondere bei Gendersternen (wie Autor\*in)
|
||||||
|
calendar:
|
||||||
|
header: 'Kalender'
|
||||||
|
info:
|
||||||
|
- >
|
||||||
|
In diesem Abschnitt kannst du deinen eigenen Kalender erstellen,
|
||||||
|
welcher in deiner Visitenkarte erscheint und den du zu deiner Kalenderapp hinzufügen kannst.
|
||||||
|
- >
|
||||||
|
Wähle aus der Liste von öffentlich gefeierten Ereignissen des Queeren Kalenders
|
||||||
|
oder füge deine eigenen persönlichen Ereignisse hinzu.
|
||||||
|
Beispiele sind Jahrestage des Coming-outs, der Beginn einer HRT, der Tag einer Namensänderung, Jahrestage in deinen Beziehungen etc.
|
||||||
|
customEvents:
|
||||||
|
header: 'Persönliche Ereignisse'
|
||||||
|
disclaimer: 'Dieses Ereignis ist ein persönliches Ereignis, welches von der Person dieser Visitenkarte erstellt wurde'
|
||||||
|
name: 'Ereignisname (z.B. „HRT begonnen“)'
|
||||||
|
month: 'Monat'
|
||||||
|
day: 'Tag'
|
||||||
|
comment: 'Kommentar (optional)'
|
||||||
|
validation:
|
||||||
|
missingName: 'Ereignisname ist erforderlich'
|
||||||
|
missingDate: 'Datum ist erforderlich'
|
||||||
|
invalidDate: 'Datum ist ungültig'
|
||||||
|
publicEvents:
|
||||||
|
header: 'Ereignisse aus dem Queeren Kalender'
|
||||||
|
|
||||||
share: 'Teilen'
|
share: 'Teilen'
|
||||||
|
|
||||||
@ -1160,6 +1200,8 @@ calendar:
|
|||||||
list: 'Ereignisliste'
|
list: 'Ereignisliste'
|
||||||
link: 'Link'
|
link: 'Link'
|
||||||
full: 'Ganzer Kalender'
|
full: 'Ganzer Kalender'
|
||||||
|
onlyFirstDays: 'Version, bei der bei langen Ereignissen nur der jeweils erste Tag eingetragen ist'
|
||||||
|
start: 'Beginn'
|
||||||
|
|
||||||
supportBanners:
|
supportBanners:
|
||||||
ukraine:
|
ukraine:
|
||||||
|
@ -126,7 +126,7 @@ export default [
|
|||||||
'footer.source',
|
'footer.source',
|
||||||
'error.invalidImage',
|
'error.invalidImage',
|
||||||
'profile.banner',
|
'profile.banner',
|
||||||
'pronoun.example',
|
'profile.example',
|
||||||
'calendar.onlyFirstDays',
|
'calendar.onlyFirstDays',
|
||||||
'calendar.start',
|
'calendar.start',
|
||||||
'calendar.events.nonmonogamy_visibility_day',
|
'calendar.events.nonmonogamy_visibility_day',
|
||||||
|
@ -358,8 +358,7 @@ contact:
|
|||||||
team:
|
team:
|
||||||
name: 'The “Neutral Language Council” collective' # TODO
|
name: 'The “Neutral Language Council” collective' # TODO
|
||||||
nameShort: 'Collective'
|
nameShort: 'Collective'
|
||||||
description: # TODO
|
description: > # TODO
|
||||||
- >
|
|
||||||
We are a queer collective dedicated to assembling, researching, shaping and promoting
|
We are a queer collective dedicated to assembling, researching, shaping and promoting
|
||||||
gender neutral and nonbinary language.
|
gender neutral and nonbinary language.
|
||||||
We also support actions towards equality and social justice.
|
We also support actions towards equality and social justice.
|
||||||
|
@ -84,7 +84,7 @@ export default ({ app, store }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.router.afterEach(() => {
|
app.router.afterEach(() => {
|
||||||
if (typeof window !== 'undefined' && window.fusetag) {
|
if (typeof window !== 'undefined' && window.fusetag && window.fusetag.pageInit) {
|
||||||
window.fusetag.pageInit();
|
window.fusetag.pageInit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -19,6 +19,16 @@ export const buildList = (fn, ...args) => {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deepGet = (obj, path) => {
|
||||||
|
let value = obj;
|
||||||
|
for (let part of path.split('.')) {
|
||||||
|
value = value[part];
|
||||||
|
if (value === undefined) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
export const head = ({title, description, banner, noindex = false, keywords}) => {
|
export const head = ({title, description, banner, noindex = false, keywords}) => {
|
||||||
const meta = { meta: [] };
|
const meta = { meta: [] };
|
||||||
|
|
||||||
|
11
src/stats.js
11
src/stats.js
@ -4,19 +4,10 @@ import Plausible from 'plausible-api';
|
|||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import { ulid } from 'ulid';
|
import { ulid } from 'ulid';
|
||||||
import expectedTranslations from '../locale/expectedTranslations.js';
|
import expectedTranslations from '../locale/expectedTranslations.js';
|
||||||
|
import { deepGet } from './helpers.js';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import Suml from 'suml';
|
import Suml from 'suml';
|
||||||
|
|
||||||
const deepGet = (obj, path) => {
|
|
||||||
let value = obj;
|
|
||||||
for (let part of path.split('.')) {
|
|
||||||
value = value[part];
|
|
||||||
if (value === undefined) { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatDate = d => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
|
const formatDate = d => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
export const buildChart = (rows, cumulative = true) => {
|
export const buildChart = (rows, cumulative = true) => {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { deepGet } from './helpers.js';
|
||||||
import translations from '../data/translations.suml';
|
import translations from '../data/translations.suml';
|
||||||
import baseTranslations from '../locale/_base/translations.suml';
|
import baseTranslations from '../locale/_base/translations.suml';
|
||||||
import expectedTranslations from '../locale/expectedTranslations.js';
|
import expectedTranslations from '../locale/expectedTranslations.js';
|
||||||
@ -17,9 +18,8 @@ class Translator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(key, warn = false, base = false, useFallback = true) {
|
get(key, warn = false, base = false, useFallback = true) {
|
||||||
let value = base ? this.baseTranslations : this.translations;
|
const translations = base ? this.baseTranslations : this.translations;
|
||||||
for (let part of key.split('.')) {
|
const value = deepGet(translations, key);
|
||||||
value = value[part];
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
if (warn) {
|
if (warn) {
|
||||||
console.error('Cannot find translation: ' + key);
|
console.error('Cannot find translation: ' + key);
|
||||||
@ -27,8 +27,6 @@ class Translator {
|
|||||||
if (!base && useFallback) {
|
if (!base && useFallback) {
|
||||||
return this.get(key, warn, true);
|
return this.get(key, warn, true);
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
69
test/translations.test.js
Normal file
69
test/translations.test.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { expect, test } from '@jest/globals';
|
||||||
|
|
||||||
|
import { loadSumlFromBase } from '../server/loader.js';
|
||||||
|
import { deepGet } from '../src/helpers.js';
|
||||||
|
import expectedTranslations from '../locale/expectedTranslations.js';
|
||||||
|
import locales from '../locale/locales.js';
|
||||||
|
|
||||||
|
const baseTranslations = loadSumlFromBase('locale/_base/translations');
|
||||||
|
const typeFlexibleKeys = new Set(['home.generator.alt']);
|
||||||
|
|
||||||
|
function specificTypeOf(value) {
|
||||||
|
if (typeof(value) === 'object') {
|
||||||
|
if (value === null) {
|
||||||
|
return null;
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
return 'array';
|
||||||
|
} else {
|
||||||
|
return 'object';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return typeof(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toMatchBaseTranslationsSchema(actual) {
|
||||||
|
const messages = recursivelyValidateSchema(actual, baseTranslations);
|
||||||
|
if (messages.length > 0) {
|
||||||
|
return {
|
||||||
|
message: () =>
|
||||||
|
`expected translations to match schema of base translations\n\n${messages.join('\n')}`,
|
||||||
|
pass: false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
message: () =>
|
||||||
|
'expected translations to mismatch schema of base translations',
|
||||||
|
pass: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function recursivelyValidateSchema(actual, base, parentKey = '') {
|
||||||
|
const messages = [];
|
||||||
|
for (const [property, value] of Object.entries(actual)) {
|
||||||
|
const key = parentKey ? `${parentKey}.${property}` : property;
|
||||||
|
if (base[property] === undefined || base[property] === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (value !== null && !typeFlexibleKeys.has(key) && specificTypeOf(value) !== specificTypeOf(base[property])) {
|
||||||
|
messages.push(`${key} has type ${specificTypeOf(value)}, expected ${specificTypeOf(base[property])}`);
|
||||||
|
}
|
||||||
|
if (specificTypeOf(value) === 'object') {
|
||||||
|
messages.push(...recursivelyValidateSchema(value, base[property], key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
test.each(locales)('translations of $code match schema of base translations', ({ code }) => {
|
||||||
|
const translations = loadSumlFromBase(`locale/${code}/translations`);
|
||||||
|
expect(translations).toMatchBaseTranslationSchema();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('expected translations are defined in base translations', () => {
|
||||||
|
const undefinedTranslations = expectedTranslations.filter(key => deepGet(baseTranslations, key) === undefined);
|
||||||
|
expect(undefinedTranslations).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect.extend({ toMatchBaseTranslationSchema: toMatchBaseTranslationsSchema });
|
Loading…
x
Reference in New Issue
Block a user