or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cardinal-pluralization.mdcore-pluralization.mdexample-values.mdindex.mdordinal-pluralization.mdplural-categories.mdrange-pluralization.md

plural-categories.mddocs/

0

# Plural Categories

1

2

Metadata about available plural categories for each language, including both cardinal and ordinal categories. This module provides the category information without the pluralization logic.

3

4

## Capabilities

5

6

### Category Objects

7

8

Each language provides an object with arrays of available categories for cardinal and ordinal pluralization.

9

10

```typescript { .api }

11

/**

12

* Language category metadata

13

*/

14

interface LanguageCategories {

15

cardinal: PluralCategory[];

16

ordinal: PluralCategory[];

17

}

18

19

type PluralCategory = "zero" | "one" | "two" | "few" | "many" | "other";

20

```

21

22

### Import Pattern

23

24

```javascript { .api }

25

import * as Categories from "make-plural/pluralCategories";

26

// Or import specific languages

27

import { en, ar, fr } from "make-plural/pluralCategories";

28

```

29

30

### Language Category Objects

31

32

All 219 languages provide category metadata:

33

34

**Examples by Complexity:**

35

36

**Simple Two-Category Languages:**

37

```javascript

38

Categories.en.cardinal // ["one", "other"]

39

Categories.de.cardinal // ["one", "other"]

40

Categories.nl.cardinal // ["one", "other"]

41

Categories.sv.cardinal // ["one", "other"]

42

```

43

44

**Three-Category Languages:**

45

```javascript

46

Categories.fr.cardinal // ["one", "many", "other"]

47

Categories.pt.cardinal // ["one", "many", "other"]

48

Categories.es.cardinal // ["one", "many", "other"]

49

Categories.it.cardinal // ["one", "many", "other"]

50

```

51

52

**Four-Category Languages:**

53

```javascript

54

Categories.pl.cardinal // ["one", "few", "many", "other"]

55

Categories.ru.cardinal // ["one", "few", "many", "other"]

56

Categories.uk.cardinal // ["one", "few", "many", "other"]

57

Categories.hr.cardinal // ["one", "few", "many", "other"]

58

```

59

60

**Complex Six-Category Languages:**

61

```javascript

62

Categories.ar.cardinal // ["zero", "one", "two", "few", "many", "other"]

63

Categories.cy.cardinal // ["zero", "one", "two", "few", "many", "other"]

64

```

65

66

**Single-Category Languages:**

67

```javascript

68

Categories.zh.cardinal // ["other"]

69

Categories.ja.cardinal // ["other"]

70

Categories.ko.cardinal // ["other"]

71

Categories.vi.cardinal // ["other"]

72

```

73

74

### Ordinal Categories

75

76

Languages with ordinal rules (105 languages) provide ordinal category arrays:

77

78

**English Ordinals:**

79

```javascript

80

Categories.en.cardinal // ["one", "other"]

81

Categories.en.ordinal // ["one", "two", "few", "other"]

82

```

83

84

**Welsh Complex Ordinals:**

85

```javascript

86

Categories.cy.cardinal // ["zero", "one", "two", "few", "many", "other"]

87

Categories.cy.ordinal // ["zero", "one", "two", "few", "many", "other"]

88

```

89

90

**French Simple Ordinals:**

91

```javascript

92

Categories.fr.cardinal // ["one", "many", "other"]

93

Categories.fr.ordinal // ["one", "other"]

94

```

95

96

**Languages Without Ordinal Rules:**

97

```javascript

98

Categories.zh.cardinal // ["other"]

99

Categories.zh.ordinal // ["other"]

100

101

Categories.ja.cardinal // ["other"]

102

Categories.ja.ordinal // ["other"]

103

```

104

105

### Usage Examples

106

107

**Checking Available Categories:**

108

```javascript

109

import * as Categories from "make-plural/pluralCategories";

110

111

// Check what categories a language supports

112

function getLanguageInfo(lang) {

113

const langCategories = Categories[lang];

114

return {

115

cardinalCount: langCategories.cardinal.length,

116

ordinalCount: langCategories.ordinal.length,

117

hasComplexCardinals: langCategories.cardinal.length > 2,

118

hasComplexOrdinals: langCategories.ordinal.length > 2,

119

categories: langCategories

120

};

121

}

122

123

console.log(getLanguageInfo('en'));

124

// {

125

// cardinalCount: 2,

126

// ordinalCount: 4,

127

// hasComplexCardinals: false,

128

// hasComplexOrdinals: true,

129

// categories: { cardinal: ["one", "other"], ordinal: ["one", "two", "few", "other"] }

130

// }

131

132

console.log(getLanguageInfo('ar'));

133

// {

134

// cardinalCount: 6,

135

// ordinalCount: 1,

136

// hasComplexCardinals: true,

137

// hasComplexOrdinals: false,

138

// categories: { cardinal: ["zero", "one", "two", "few", "many", "other"], ordinal: ["other"] }

139

// }

140

```

141

142

**Building Localization Systems:**

143

```javascript

144

import * as Categories from "make-plural/pluralCategories";

145

146

// Generate template objects for translations

147

function generateTranslationTemplate(languages) {

148

const template = {};

149

150

for (const lang of languages) {

151

template[lang] = {

152

cardinal: {},

153

ordinal: {}

154

};

155

156

// Create empty slots for each category

157

Categories[lang].cardinal.forEach(category => {

158

template[lang].cardinal[category] = "";

159

});

160

161

Categories[lang].ordinal.forEach(category => {

162

template[lang].ordinal[category] = "";

163

});

164

}

165

166

return template;

167

}

168

169

const template = generateTranslationTemplate(['en', 'fr', 'ar']);

170

console.log(template);

171

// {

172

// en: {

173

// cardinal: { one: "", other: "" },

174

// ordinal: { one: "", two: "", few: "", other: "" }

175

// },

176

// fr: {

177

// cardinal: { one: "", many: "", other: "" },

178

// ordinal: { one: "", other: "" }

179

// },

180

// ar: {

181

// cardinal: { zero: "", one: "", two: "", few: "", many: "", other: "" },

182

// ordinal: { other: "" }

183

// }

184

// }

185

```

186

187

**Validation and Analysis:**

188

```javascript

189

import * as Categories from "make-plural/pluralCategories";

190

191

// Analyze language complexity

192

function analyzeLanguageComplexity() {

193

const analysis = {

194

simple: [], // 1-2 categories

195

moderate: [], // 3-4 categories

196

complex: [] // 5-6 categories

197

};

198

199

for (const [lang, categories] of Object.entries(Categories)) {

200

const cardinalCount = categories.cardinal.length;

201

202

if (cardinalCount <= 2) {

203

analysis.simple.push(lang);

204

} else if (cardinalCount <= 4) {

205

analysis.moderate.push(lang);

206

} else {

207

analysis.complex.push(lang);

208

}

209

}

210

211

return analysis;

212

}

213

214

// Find languages with ordinal rules

215

function getOrdinalLanguages() {

216

return Object.entries(Categories)

217

.filter(([lang, categories]) =>

218

categories.ordinal.length > 1 ||

219

(categories.ordinal.length === 1 && categories.ordinal[0] !== "other")

220

)

221

.map(([lang]) => lang);

222

}

223

224

console.log(getOrdinalLanguages().length); // 105

225

```

226

227

### Practical Applications

228

229

**Form Generation:**

230

```javascript

231

import * as Categories from "make-plural/pluralCategories";

232

233

// Generate form fields for translation interface

234

function generatePluralForm(language, type = 'cardinal') {

235

const categories = Categories[language][type];

236

237

return categories.map(category => ({

238

field: `${language}_${type}_${category}`,

239

label: `${language} ${type} ${category}`,

240

placeholder: `Enter ${category} form...`

241

}));

242

}

243

```

244

245

**Validation:**

246

```javascript

247

import * as Categories from "make-plural/pluralCategories";

248

249

// Validate translation completeness

250

function validateTranslations(translations, language) {

251

const required = Categories[language];

252

const errors = [];

253

254

// Check cardinal categories

255

required.cardinal.forEach(category => {

256

if (!translations[language]?.cardinal?.[category]) {

257

errors.push(`Missing cardinal ${category} for ${language}`);

258

}

259

});

260

261

// Check ordinal categories

262

required.ordinal.forEach(category => {

263

if (!translations[language]?.ordinal?.[category]) {

264

errors.push(`Missing ordinal ${category} for ${language}`);

265

}

266

});

267

268

return errors;

269

}

270

```

271

272

### Category Distribution

273

274

**By Cardinal Category Count:**

275

- 1 category (other only): 44 languages (Chinese, Japanese, Korean, etc.)

276

- 2 categories (one, other): 81 languages (English, German, Italian, etc.)

277

- 3 categories: 34 languages (French, Portuguese, Spanish, etc.)

278

- 4 categories: 37 languages (Polish, Russian, Czech, etc.)

279

- 5 categories: 8 languages (Romanian, Lithuanian, etc.)

280

- 6 categories: 15 languages (Arabic, Welsh, Breton, etc.)

281

282

**Ordinal Complexity:**

283

- 105 languages have specific ordinal rules

284

- 114 languages use default "other" category for ordinals

285

- English has the most complex common ordinal system (4 categories)

286

- Welsh and other Celtic languages have the most complex ordinal systems (6 categories)