mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-03 11:07:00 -04:00
(de)(nouns) grammar tables for noun conventions
This commit is contained in:
parent
d54b2c912c
commit
ec5f0ba97d
@ -13,12 +13,6 @@ const routerOptions: RouterOptions = {
|
||||
// before user plugins with enforce: pre are run
|
||||
const config = await loadConfig();
|
||||
return routes.flatMap((route) => {
|
||||
// workaround for dynamic inclusion of nouns subroutes,
|
||||
// as translatedPaths does not work because definePageMeta is not scanned in pages:extend hook in Nuxt 3
|
||||
if (typeof route.name === 'string' &&
|
||||
route.name.startsWith('nouns-') && !route.name.startsWith(`nouns-${config.locale}`)) {
|
||||
return [];
|
||||
}
|
||||
if (route.meta?.translatedPaths) {
|
||||
const translatedPaths = route.meta.translatedPaths(config);
|
||||
if (translatedPaths.length === 0) {
|
||||
@ -36,6 +30,11 @@ const routerOptions: RouterOptions = {
|
||||
meta: translatedRoute.meta,
|
||||
};
|
||||
});
|
||||
} else if (typeof route.name === 'string' &&
|
||||
route.name.startsWith('nouns-') && !route.name.startsWith(`nouns-${config.locale}`)) {
|
||||
// workaround for dynamic inclusion of nouns subroutes,
|
||||
// as translatedPaths does not work because definePageMeta is not scanned in pages:extend hook in Nuxt 3
|
||||
return [];
|
||||
}
|
||||
return [route];
|
||||
});
|
||||
|
@ -79,7 +79,7 @@ const links = computed((): HeaderLink[] => {
|
||||
}
|
||||
|
||||
if (config.nouns.enabled) {
|
||||
const extras = [];
|
||||
const extras = ['nouns-convention'];
|
||||
for (const subroute of config.nouns.subroutes || []) {
|
||||
extras.push(`/${subroute}`);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ export default withNuxt(
|
||||
eslintPluginJsonSchemaValidator.configs['flat/base'],
|
||||
{
|
||||
name: 'pronouns-page/validation',
|
||||
files: ['locale/*/config.suml'],
|
||||
files: ['locale/**/*.suml'],
|
||||
rules: {
|
||||
'json-schema-validator/no-invalid': ['error', {
|
||||
schemas: [
|
||||
@ -94,6 +94,10 @@ export default withNuxt(
|
||||
fileMatch: ['locale/*/config.suml'],
|
||||
schema: 'locale/config.schema.json',
|
||||
},
|
||||
{
|
||||
fileMatch: ['locale/*/nouns/nounConventions.suml'],
|
||||
schema: 'locale/nounConventions.schema.json',
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
|
@ -2,11 +2,14 @@ import type { MorphemeCell, VariantsFromBaseConverter } from '~/src/language/gra
|
||||
|
||||
const cases = ['n', 'g', 'd', 'a'];
|
||||
|
||||
interface Declension {
|
||||
interface Category {
|
||||
name: string;
|
||||
abbreviation: string;
|
||||
}
|
||||
|
||||
interface Declension extends Category {
|
||||
numerus: 'singular' | 'plural';
|
||||
icon?: string;
|
||||
abbreviation: string;
|
||||
}
|
||||
|
||||
const declensions: Declension[] = [
|
||||
@ -41,8 +44,37 @@ const declensions: Declension[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const morphemesByCase = (morphemeBase: string): MorphemeCell[] => {
|
||||
return cases.map((caseAbbreviation) => ({ morpheme: `${morphemeBase}_${caseAbbreviation}` }));
|
||||
const definitenessCategories: Category[] = [
|
||||
{
|
||||
name: 'bestimmt',
|
||||
abbreviation: '',
|
||||
},
|
||||
{
|
||||
name: 'unbestimmt',
|
||||
abbreviation: 'indefinite_',
|
||||
},
|
||||
];
|
||||
|
||||
const adjectiveDeclensions: Category[] = [
|
||||
{
|
||||
name: 'schwach',
|
||||
abbreviation: 'weak',
|
||||
},
|
||||
{
|
||||
name: 'gemischt',
|
||||
abbreviation: 'mixed',
|
||||
},
|
||||
{
|
||||
name: 'stark',
|
||||
abbreviation: 'strong',
|
||||
},
|
||||
];
|
||||
|
||||
const morphemesByCase = (
|
||||
morphemeBase: string,
|
||||
attributes: Pick<MorphemeCell, 'prefix' | 'suffix'> = {},
|
||||
): MorphemeCell[] => {
|
||||
return cases.map((caseAbbreviation) => ({ morpheme: `${morphemeBase}_${caseAbbreviation}`, ...attributes }));
|
||||
};
|
||||
|
||||
export default {
|
||||
@ -57,4 +89,19 @@ export default {
|
||||
morphemeCells: morphemesByCase(`${sectionVariants.base}_${declension.abbreviation}`),
|
||||
}));
|
||||
},
|
||||
'definiteness-with-case': (sectionVariants) => {
|
||||
return definitenessCategories.map((definitenessCategory) => ({
|
||||
name: definitenessCategory.name,
|
||||
morphemeCells: morphemesByCase(`${definitenessCategory.abbreviation}${sectionVariants.base}`),
|
||||
}));
|
||||
},
|
||||
'adjective-declension-with-case': (sectionVariants) => {
|
||||
return adjectiveDeclensions.map((adjectiveDeclension) => {
|
||||
const morphemeBase = `${sectionVariants.base}_${adjectiveDeclension.abbreviation}`;
|
||||
return {
|
||||
name: adjectiveDeclension.name,
|
||||
morphemeCells: morphemesByCase(morphemeBase, { prefix: { spelling: '-' } }),
|
||||
};
|
||||
});
|
||||
},
|
||||
} satisfies VariantsFromBaseConverter;
|
||||
|
402
locale/de/nouns/nounConventions.suml
Normal file
402
locale/de/nouns/nounConventions.suml
Normal file
@ -0,0 +1,402 @@
|
||||
morphemes:
|
||||
- 'article_n'
|
||||
- 'article_g'
|
||||
- 'article_d'
|
||||
- 'article_a'
|
||||
- 'indefinite_article_n'
|
||||
- 'indefinite_article_g'
|
||||
- 'indefinite_article_d'
|
||||
- 'indefinite_article_a'
|
||||
- 'adjective_weak_n'
|
||||
- 'adjective_weak_g'
|
||||
- 'adjective_weak_d'
|
||||
- 'adjective_weak_a'
|
||||
- 'adjective_mixed_n'
|
||||
- 'adjective_mixed_g'
|
||||
- 'adjective_mixed_d'
|
||||
- 'adjective_mixed_a'
|
||||
- 'adjective_strong_n'
|
||||
- 'adjective_strong_g'
|
||||
- 'adjective_strong_d'
|
||||
- 'adjective_strong_a'
|
||||
grammarTables:
|
||||
-
|
||||
columnHeader:
|
||||
-
|
||||
name: 'Nominativ'
|
||||
short: 'N'
|
||||
-
|
||||
name: 'Genitiv'
|
||||
short: 'G'
|
||||
-
|
||||
name: 'Dativ'
|
||||
short: 'D'
|
||||
-
|
||||
name: 'Akkusativ'
|
||||
short: 'A'
|
||||
sections:
|
||||
-
|
||||
header:
|
||||
name: 'Artikel'
|
||||
variants:
|
||||
base: 'article'
|
||||
type: 'definiteness-with-case'
|
||||
-
|
||||
header:
|
||||
name: 'Adjektivdeklination'
|
||||
variants:
|
||||
base: 'adjective'
|
||||
type: 'adjective-declension-with-case'
|
||||
conventions:
|
||||
maskulinum:
|
||||
name: 'Maskulinum'
|
||||
normative: true
|
||||
morphemes:
|
||||
article_n: 'der'
|
||||
article_g: 'des'
|
||||
article_d: 'dem'
|
||||
article_a: 'den'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'eines'
|
||||
indefinite_article_d: 'einem'
|
||||
indefinite_article_a: 'einen'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'er'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'en'
|
||||
adjective_strong_n: 'er'
|
||||
adjective_strong_g: 'en'
|
||||
adjective_strong_d: 'em'
|
||||
adjective_strong_a: 'en'
|
||||
femininum:
|
||||
name: 'Femininum'
|
||||
normative: true
|
||||
morphemes:
|
||||
article_n: 'die'
|
||||
article_g: 'der'
|
||||
article_d: 'der'
|
||||
article_a: 'die'
|
||||
indefinite_article_n: 'eine'
|
||||
indefinite_article_g: 'einer'
|
||||
indefinite_article_d: 'einer'
|
||||
indefinite_article_a: 'eine'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e'
|
||||
adjective_strong_n: 'e'
|
||||
adjective_strong_g: 'er'
|
||||
adjective_strong_d: 'er'
|
||||
adjective_strong_a: 'e'
|
||||
diminuitiv:
|
||||
name: 'Diminuitiv'
|
||||
normative: true
|
||||
morphemes:
|
||||
article_n: 'das'
|
||||
article_g: 'des'
|
||||
article_d: 'dem'
|
||||
article_a: 'das'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'eines'
|
||||
indefinite_article_d: 'einem'
|
||||
indefinite_article_a: 'ein'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'es'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'es'
|
||||
adjective_strong_n: 'es'
|
||||
adjective_strong_g: 'en'
|
||||
adjective_strong_d: 'em'
|
||||
adjective_strong_a: 'es'
|
||||
person-formen:
|
||||
name: 'Person-Formen'
|
||||
normative: true
|
||||
morphemes:
|
||||
article_n: 'die'
|
||||
article_g: 'der'
|
||||
article_d: 'der'
|
||||
article_a: 'die'
|
||||
indefinite_article_n: 'eine'
|
||||
indefinite_article_g: 'einer'
|
||||
indefinite_article_d: 'einer'
|
||||
indefinite_article_a: 'eine'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e'
|
||||
adjective_strong_n: 'e'
|
||||
adjective_strong_g: 'er'
|
||||
adjective_strong_d: 'er'
|
||||
adjective_strong_a: 'e'
|
||||
mensch-formen:
|
||||
name: 'Mensch-Formen'
|
||||
normative: true
|
||||
morphemes:
|
||||
article_n: 'der'
|
||||
article_g: 'des'
|
||||
article_d: 'dem'
|
||||
article_a: 'den'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'eines'
|
||||
indefinite_article_d: 'einem'
|
||||
indefinite_article_a: 'einen'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'er'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'en'
|
||||
adjective_strong_n: 'er'
|
||||
adjective_strong_g: 'en'
|
||||
adjective_strong_d: 'em'
|
||||
adjective_strong_a: 'en'
|
||||
y-formen:
|
||||
name: 'Y-Formen'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'das'
|
||||
article_g: 'des'
|
||||
article_d: 'dem'
|
||||
article_a: 'das'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'eines'
|
||||
indefinite_article_d: 'einem'
|
||||
indefinite_article_a: 'ein'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'es'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'es'
|
||||
adjective_strong_n: 'es'
|
||||
adjective_strong_g: 'en'
|
||||
adjective_strong_d: 'em'
|
||||
adjective_strong_a: 'es'
|
||||
i-formen:
|
||||
name: 'I-Formen'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'das'
|
||||
article_g: 'des'
|
||||
article_d: 'dem'
|
||||
article_a: 'das'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'eines'
|
||||
indefinite_article_d: 'einem'
|
||||
indefinite_article_a: 'ein'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'es'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'es'
|
||||
adjective_strong_n: 'es'
|
||||
adjective_strong_g: 'en'
|
||||
adjective_strong_d: 'em'
|
||||
adjective_strong_a: 'es'
|
||||
inklusivum:
|
||||
name: 'Inklusivum'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'de'
|
||||
article_g: 'ders'
|
||||
article_d: 'derm'
|
||||
article_a: 'de'
|
||||
indefinite_article_n: 'ein'
|
||||
indefinite_article_g: 'einers'
|
||||
indefinite_article_d: 'einerm'
|
||||
indefinite_article_a: 'ein'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e'
|
||||
adjective_strong_n: 'ey'
|
||||
adjective_strong_g: 'ers'
|
||||
adjective_strong_d: 'erm'
|
||||
adjective_strong_a: 'ey'
|
||||
indefinitivum:
|
||||
name: 'Indefinitivum'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'din'
|
||||
article_g: 'dins'
|
||||
article_d: 'dim'
|
||||
article_a: 'din'
|
||||
indefinite_article_n: 'einin'
|
||||
indefinite_article_g: 'einins'
|
||||
indefinite_article_d: 'einim'
|
||||
indefinite_article_a: 'einir'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'in'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'in'
|
||||
ens-formen:
|
||||
name: 'ens-Formen'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'dens'
|
||||
article_g: 'dens'
|
||||
article_d: 'dens'
|
||||
article_a: 'dens'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'e'
|
||||
adjective_weak_d: 'e'
|
||||
adjective_weak_a: 'e'
|
||||
ex-formen:
|
||||
name: 'ex-Formen'
|
||||
normative: false
|
||||
morphemes: {}
|
||||
ojum:
|
||||
name: 'Ojum'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'dej'
|
||||
article_g: 'dejs'
|
||||
article_d: 'dojm'
|
||||
article_a: 'dojn'
|
||||
nona-system:
|
||||
name: 'NoNa-System'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'dai'
|
||||
article_g: 'dais'
|
||||
article_d: 'dam'
|
||||
article_a: 'dai'
|
||||
indefinite_article_n: 'eint'
|
||||
indefinite_article_g: 'einter'
|
||||
indefinite_article_d: 'eintem'
|
||||
indefinite_article_a: 'eint'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e'
|
||||
adjective_mixed_g: 'er'
|
||||
adjective_mixed_d: 'em'
|
||||
adjective_mixed_a: 'e'
|
||||
genderdoppelpunkt:
|
||||
name: 'Genderdoppelpunkt'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'der:die'
|
||||
article_g: 'des:der'
|
||||
article_d: 'dem:der'
|
||||
article_a: 'den:die'
|
||||
indefinite_article_n: 'ein:e'
|
||||
indefinite_article_g: 'einer:s'
|
||||
indefinite_article_d: 'einer:m'
|
||||
indefinite_article_a: 'eine:n'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e:r'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e:n'
|
||||
adjective_strong_n: 'e:r'
|
||||
adjective_strong_g: 'er:n'
|
||||
adjective_strong_d: 'er:m'
|
||||
adjective_strong_a: 'e:n'
|
||||
gendergap:
|
||||
name: 'Gendergap'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'der_die'
|
||||
article_g: 'des_der'
|
||||
article_d: 'dem_der'
|
||||
article_a: 'den_die'
|
||||
indefinite_article_n: 'ein_e'
|
||||
indefinite_article_g: 'einer_s'
|
||||
indefinite_article_d: 'einer_m'
|
||||
indefinite_article_a: 'eine_n'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e_r'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e_n'
|
||||
adjective_strong_n: 'e_r'
|
||||
adjective_strong_g: 'er_n'
|
||||
adjective_strong_d: 'er_m'
|
||||
adjective_strong_a: 'e_n'
|
||||
gendersternchen:
|
||||
name: 'Gendersternchen'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'der*die'
|
||||
article_g: 'des*der'
|
||||
article_d: 'dem*der'
|
||||
article_a: 'den*die'
|
||||
indefinite_article_n: 'ein*e'
|
||||
indefinite_article_g: 'einer*s'
|
||||
indefinite_article_d: 'einer*m'
|
||||
indefinite_article_a: 'eine*n'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'e*r'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'e*n'
|
||||
adjective_strong_n: 'e*r'
|
||||
adjective_strong_g: 'er*n'
|
||||
adjective_strong_d: 'er*m'
|
||||
adjective_strong_a: 'e*n'
|
||||
binnen-i:
|
||||
name: 'Binnen-I'
|
||||
normative: false
|
||||
morphemes:
|
||||
article_n: 'derDie'
|
||||
article_g: 'desDer'
|
||||
article_d: 'demDer'
|
||||
article_a: 'denDie'
|
||||
indefinite_article_n: 'einE'
|
||||
indefinite_article_g: 'eineRs'
|
||||
indefinite_article_d: 'eineRm'
|
||||
indefinite_article_a: 'einEn'
|
||||
adjective_weak_n: 'e'
|
||||
adjective_weak_g: 'en'
|
||||
adjective_weak_d: 'en'
|
||||
adjective_weak_a: 'e'
|
||||
adjective_mixed_n: 'Er'
|
||||
adjective_mixed_g: 'en'
|
||||
adjective_mixed_d: 'en'
|
||||
adjective_mixed_a: 'En'
|
||||
adjective_strong_n: 'Er'
|
||||
adjective_strong_g: 'eRn'
|
||||
adjective_strong_d: 'eRm'
|
||||
adjective_strong_a: 'En'
|
@ -8,17 +8,20 @@ import { loadSuml } from '~/server/loader.ts';
|
||||
|
||||
const __dirname = new URL('.', import.meta.url).pathname;
|
||||
|
||||
const generateConfigJsonSchema = async () => {
|
||||
const generateJsonSchema = async (path: string, typeName: string) => {
|
||||
const schema = createGenerator({
|
||||
path: `${__dirname}/config.ts`,
|
||||
path,
|
||||
tsconfig: `${__dirname}/../tsconfig.json`,
|
||||
strictTuples: true,
|
||||
markdownDescription: true,
|
||||
// speed up schema generation; type checking happens separately
|
||||
skipTypeCheck: true,
|
||||
}).createSchema('Config');
|
||||
}).createSchema(typeName);
|
||||
|
||||
await fs.writeFile(`${__dirname}/config.schema.json`, `${JSON.stringify(schema, null, 4)}\n`);
|
||||
await fs.writeFile(
|
||||
`${__dirname}/${typeName[0].toLowerCase()}${typeName.substring(1)}.schema.json`,
|
||||
`${JSON.stringify(schema, null, 4)}\n`,
|
||||
);
|
||||
};
|
||||
|
||||
const generateFontsModule = async () => {
|
||||
@ -35,4 +38,8 @@ const generateFontsModule = async () => {
|
||||
);
|
||||
};
|
||||
|
||||
await Promise.all([generateConfigJsonSchema(), generateFontsModule()]);
|
||||
await Promise.all([
|
||||
generateJsonSchema(`${__dirname}/config.ts`, 'Config'),
|
||||
generateJsonSchema(`${__dirname}/../src/nouns.ts`, 'NounConventions'),
|
||||
generateFontsModule(),
|
||||
]);
|
||||
|
59
pages/nouns/[convention].vue
Normal file
59
pages/nouns/[convention].vue
Normal file
@ -0,0 +1,59 @@
|
||||
<script setup lang="ts">
|
||||
import { loadNounConventions } from '~/src/data.ts';
|
||||
import { MorphemeValues } from '~/src/language/morphemes.ts';
|
||||
import type { NounConvention } from '~/src/nouns.ts';
|
||||
|
||||
definePageMeta({
|
||||
translatedPaths: (config) => {
|
||||
return translatedPathByConfigModule(config.nouns).map((nounsRoute) => `${nounsRoute}/:convention`);
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const nounConventions = await loadNounConventions();
|
||||
|
||||
const findNounConvention = (nounConventionKey: string): NounConvention | undefined => {
|
||||
for (const [key, nounConvention] of Object.entries(nounConventions?.conventions ?? {})) {
|
||||
if (key === nounConventionKey) {
|
||||
return nounConvention;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const nounConvention = typeof route.params.convention === 'string'
|
||||
? findNounConvention(route.params.convention)
|
||||
: undefined;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page>
|
||||
<NotFound v-if="nounConventions === undefined || nounConvention === undefined" />
|
||||
<template v-else>
|
||||
<h2>
|
||||
<Icon v="book-alt" />
|
||||
</h2>
|
||||
|
||||
<section>
|
||||
<div class="alert alert-primary">
|
||||
<h2 class="text-center mb-0">
|
||||
<strong><Spelling :text="nounConvention.name" /></strong>
|
||||
</h2>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 class="h4">
|
||||
<Icon v="spell-check" />
|
||||
<T>pronouns.grammarTable</T><T>quotation.colon</T>
|
||||
</h2>
|
||||
<GrammarTable
|
||||
v-for="(grammarTable, t) in nounConventions.grammarTables"
|
||||
:key="t"
|
||||
:grammar-table="grammarTable"
|
||||
:morpheme-values="new MorphemeValues(nounConvention.morphemes)"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
</Page>
|
||||
</template>
|
@ -8,6 +8,7 @@ import type { Translations } from '~/locale/translations.ts';
|
||||
import { buildCalendar } from '~/src/calendar/calendar.ts';
|
||||
import { getLocaleForUrl, getUrlForLocale } from '~/src/domain.ts';
|
||||
import type { VariantsFromBaseConverter } from '~/src/language/grammarTables.ts';
|
||||
import type { NounConventions } from '~/src/nouns.ts';
|
||||
|
||||
export const getLocale = () => {
|
||||
return getLocaleForUrl(useRequestURL()) ?? '_';
|
||||
@ -62,6 +63,14 @@ export const loadPronounLibrary = async (config: Config) => {
|
||||
return new PronounLibrary(config, pronounGroups, pronouns);
|
||||
};
|
||||
|
||||
export const loadNounConventions = async (): Promise<NounConventions | undefined> => {
|
||||
try {
|
||||
return (await import(`~/locale/${getLocale()}/nouns/nounConventions.suml`)).default;
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const loadNounTemplates = async () => {
|
||||
const nounTemplatesRaw = (await import(`~/locale/${getLocale()}/nouns/nounTemplates.tsv`)).default;
|
||||
return buildList(function* () {
|
||||
|
@ -17,7 +17,12 @@ export interface MorphemeValue {
|
||||
}
|
||||
|
||||
export class MorphemeValues {
|
||||
constructor(private readonly values: Record<string, MorphemeValue | undefined>) {}
|
||||
private readonly values: Record<string, MorphemeValue | undefined>;
|
||||
|
||||
constructor(values: Record<string, MorphemeValue | string | undefined>) {
|
||||
this.values = Object.fromEntries(Object.entries(values)
|
||||
.map(([morpheme, value]) => [morpheme, value !== undefined ? toMorphemeValue(value) : undefined]));
|
||||
}
|
||||
|
||||
getSpelling(morpheme: string): string | undefined {
|
||||
let capital = false;
|
||||
|
14
src/nouns.ts
14
src/nouns.ts
@ -1,4 +1,6 @@
|
||||
import type { Config } from '~/locale/config.ts';
|
||||
import type { GrammarTableDefinition } from '~/src/language/grammarTables.ts';
|
||||
import type { MorphemeValue } from '~/src/language/morphemes.ts';
|
||||
|
||||
export const genders = ['masc', 'fem', 'neutr', 'nb'] as const;
|
||||
export type Gender = typeof genders[number];
|
||||
@ -27,3 +29,15 @@ export const longIdentifierByGender: Record<Gender, string> = {
|
||||
neutr: 'neuter',
|
||||
nb: 'nonbinary',
|
||||
};
|
||||
|
||||
export interface NounConvention {
|
||||
name: string;
|
||||
normative: boolean;
|
||||
morphemes: Record<string, MorphemeValue | string>;
|
||||
}
|
||||
|
||||
export interface NounConventions {
|
||||
morphemes: string[];
|
||||
grammarTables: GrammarTableDefinition[];
|
||||
conventions: Record<string, NounConvention>;
|
||||
}
|
||||
|
@ -7,8 +7,9 @@ import allLocales from '~/locale/locales.ts';
|
||||
import { loadSuml, loadTsv } from '~/server/loader.ts';
|
||||
import { normaliseKey } from '~/src/buildPronoun.ts';
|
||||
import { Example } from '~/src/classes.ts';
|
||||
import type { VariantsFromBaseConverter } from '~/src/language/grammarTables.ts';
|
||||
import { getBaseMorpheme } from '~/src/language/morphemes.ts';
|
||||
import { availableGenders, gendersWithNumerus } from '~/src/nouns.ts';
|
||||
import { availableGenders, gendersWithNumerus, type NounConventions } from '~/src/nouns.ts';
|
||||
|
||||
function toHaveValidMorphemes(actual: string, morphemes: string[]): SyncExpectationResult {
|
||||
const containedMorphemes = Example.parse(actual).filter((part) => part.variable)
|
||||
@ -155,4 +156,33 @@ describe.each(allLocales)('data files of $code', async ({ code }) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let nounConventions;
|
||||
try {
|
||||
nounConventions = await loadSuml<NounConventions>(`locale/${code}/nouns/nounConventions.suml`);
|
||||
} catch (error) {
|
||||
nounConventions = undefined;
|
||||
}
|
||||
|
||||
if (nounConventions !== undefined) {
|
||||
describe('nouns/nounConventions.suml', () => {
|
||||
test('has valid variant types', async () => {
|
||||
const grammarTableVariantsConverter = (await import(`~/locale/${code}/language/grammarTableVariantsConverter.ts`)).default as VariantsFromBaseConverter;
|
||||
|
||||
for (const grammarTable of nounConventions.grammarTables) {
|
||||
for (const section of grammarTable.sections) {
|
||||
if (!Array.isArray(section.variants)) {
|
||||
expect(Object.keys(grammarTableVariantsConverter)).toContain(section.variants.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
test('has valid morphemes', () => {
|
||||
for (const convention of Object.values(nounConventions.conventions)) {
|
||||
expect(nounConventions.morphemes)
|
||||
.toEqual(expect.arrayContaining(Object.keys(convention.morphemes)));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user