File Coverage

File:lib/Genealogy/Relationship/Name.pm
Coverage:96.1%

linestmtbrancondsubtimecode
1package Genealogy::Relationship::Name;
2
3# Genealogy::Relationship::Name - Return the name of a genealogical relationship
4# given step counts to and from a common ancestor, the sex of person B, and a language.
5#
6# Author: Nigel Horne <njh@nigelhorne.com>
7# Licence: GPL v2
8
9
6
6
6
584073
4
76
use strict;
10
6
6
6
8
4
108
use warnings;
11
6
6
6
1054
35527
10
use autodie qw(:all);
12
13
6
6
6
41689
3
128
use Carp qw(croak carp);
14
6
6
6
1401
124046
85
use Object::Configure;
15
6
6
6
14
4
96
use Params::Get;
16
6
6
6
8
43
67
use Params::Validate::Strict 0.31;
17
6
6
6
14
3
14603
use Readonly;
18
19our $VERSION = '0.03';
20
21# ---------------------------------------------------------------------------
22# Constants – relationship table keys
23# ---------------------------------------------------------------------------
24
25# Supported language codes
26Readonly::Array my @SUPPORTED_LANGUAGES => qw(de de_ch en es fa fr la);
27
28# Default language when none supplied
29Readonly::Scalar my $DEFAULT_LANGUAGE => 'en';
30
31# Sex constants
32Readonly::Scalar my $SEX_MALE   => 'M';
33Readonly::Scalar my $SEX_FEMALE => 'F';
34
35# ---------------------------------------------------------------------------
36# English relationship tables
37# Key: "$steps1,$steps2"  where steps1 = steps from A to ancestor,
38#                                steps2 = steps from B to ancestor
39# ---------------------------------------------------------------------------
40
41Readonly::Hash my %EN_MALE_RELATIONSHIPS => (
42        '0,0' => 'self',
43        '0,1' => 'son',
44        '0,2' => 'grandson',
45        '0,3' => 'great-grandson',
46        '0,4' => 'great-great-grandson',
47        '0,5' => 'great-great-great-grandson',
48        '0,6' => 'great-great-great-great-grandson',
49        '0,7' => 'great-great-great-great-great-grandson',
50        '0,8' => 'great-great-great-great-great-great-grandson',
51        '0,9' => 'great-great-great-great-great-great-great-grandson',
52        '0,10' => 'great-great-great-great-great-great-great-great-grandson',
53        '1,0' => 'father',
54        '1,1' => 'brother',
55        '1,2' => 'nephew',
56        '1,3' => 'great-nephew',
57        '1,4' => 'great-great-nephew',
58        '1,5' => 'great-great-great-nephew',
59        '1,6' => 'great-great-great-great-nephew',
60        '1,7' => 'great-great-great-great-great-nephew',
61        '1,8' => 'great-great-great-great-great-great-nephew',
62        '1,9' => 'great-great-great-great-great-great-great-nephew',
63        '1,10' => 'great-great-great-great-great-great-great-great-nephew',
64        '2,0' => 'grandfather',
65        '2,1' => 'uncle',
66        '2,2' => 'first cousin',
67        '2,3' => 'first cousin once-removed',
68        '2,4' => 'first cousin twice-removed',
69        '2,5' => 'first cousin three-times-removed',
70        '2,6' => 'first cousin four-times-removed',
71        '2,7' => 'first cousin five-times-removed',
72        '2,8' => 'first cousin six-times-removed',
73        '2,9' => 'first cousin seven-times-removed',
74        '2,10' => 'first cousin eight-times-removed',
75        '3,0' => 'great-grandfather',
76        '3,1' => 'great-uncle',
77        '3,2' => 'first cousin once-removed',
78        '3,3' => 'second cousin',
79        '3,4' => 'second cousin once-removed',
80        '3,5' => 'second cousin twice-removed',
81        '3,6' => 'second cousin three-times-removed',
82        '3,7' => 'second cousin four-times-removed',
83        '3,8' => 'second cousin five-times-removed',
84        '3,9' => 'second cousin six-times-removed',
85        '3,10' => 'second cousin seven-times-removed',
86        '4,0' => 'great-great-grandfather',
87        '4,1' => 'great-great-uncle',
88        '4,2' => 'first cousin twice-removed',
89        '4,3' => 'second cousin once-removed',
90        '4,4' => 'third cousin',
91        '4,5' => 'third cousin once-removed',
92        '4,6' => 'third cousin twice-removed',
93        '4,7' => 'third cousin three-times-removed',
94        '4,8' => 'third cousin four-times-removed',
95        '4,9' => 'third cousin five-times-removed',
96        '4,10' => 'third cousin six-times-removed',
97        '5,0' => 'great-great-great-grandfather',
98        '5,1' => 'great-great-great-uncle',
99        '5,2' => 'first cousin three-times-removed',
100        '5,3' => 'second cousin twice-removed',
101        '5,4' => 'third cousin once-removed',
102        '5,5' => 'fourth cousin',
103        '5,6' => 'fourth cousin once-removed',
104        '5,7' => 'fourth cousin twice-removed',
105        '5,8' => 'fourth cousin three-times-removed',
106        '5,9' => 'fourth cousin four-times-removed',
107        '5,10' => 'fourth cousin five-times-removed',
108        '6,0' => 'great-great-great-great-grandfather',
109        '6,1' => 'great-great-great-great-uncle',
110        '6,2' => 'first cousin four-times-removed',
111        '6,3' => 'second cousin three-times-removed',
112        '6,4' => 'third cousin twice-removed',
113        '6,5' => 'fourth cousin once-removed',
114        '6,6' => 'fifth cousin',
115        '6,7' => 'fifth cousin once-removed',
116        '6,8' => 'fifth cousin twice-removed',
117        '6,9' => 'fifth cousin three-times-removed',
118        '6,10' => 'fifth cousin four-times-removed',
119        '7,0' => 'great-great-great-great-great-grandfather',
120        '7,1' => 'great-great-great-great-great-uncle',
121        '7,2' => 'first cousin five-times-removed',
122        '7,3' => 'second cousin four-times-removed',
123        '7,4' => 'third cousin three-times-removed',
124        '7,5' => 'fourth cousin twice-removed',
125        '7,6' => 'fifth cousin once-removed',
126        '7,7' => 'sixth cousin',
127        '7,8' => 'sixth cousin once-removed',
128        '7,9' => 'sixth cousin twice-removed',
129        '7,10' => 'sixth cousin three-times-removed',
130        '8,0' => 'great-great-great-great-great-great-grandfather',
131        '8,1' => 'great-great-great-great-great-great-uncle',
132        '8,2' => 'first cousin six-times-removed',
133        '8,3' => 'second cousin five-times-removed',
134        '8,4' => 'third cousin four-times-removed',
135        '8,5' => 'fourth cousin three-times-removed',
136        '8,6' => 'fifth cousin twice-removed',
137        '8,7' => 'sixth cousin once-removed',
138        '8,8' => 'seventh cousin',
139        '8,9' => 'seventh cousin once-removed',
140        '8,10' => 'seventh cousin twice-removed',
141        '9,0' => 'great-great-great-great-great-great-great-grandfather',
142        '9,1' => 'great-great-great-great-great-great-great-uncle',
143        '9,2' => 'first cousin seven-times-removed',
144        '9,3' => 'second cousin six-times-removed',
145        '9,4' => 'third cousin five-times-removed',
146        '9,5' => 'fourth cousin four-times-removed',
147        '9,6' => 'fifth cousin three-times-removed',
148        '9,7' => 'sixth cousin twice-removed',
149        '9,8' => 'seventh cousin once-removed',
150        '9,9' => 'eighth cousin',
151        '9,10' => 'eighth cousin once-removed',
152        '10,0' => 'great-great-great-great-great-great-great-great-grandfather',
153        '10,1' => 'great-great-great-great-great-great-great-great-uncle',
154        '10,2' => 'first cousin eight-times-removed',
155        '10,3' => 'second cousin seven-times-removed',
156        '10,4' => 'third cousin six-times-removed',
157        '10,5' => 'fourth cousin five-times-removed',
158        '10,6' => 'fifth cousin four-times-removed',
159        '10,7' => 'sixth cousin three-times-removed',
160        '10,8' => 'seventh cousin twice-removed',
161        '10,9' => 'eighth cousin once-removed',
162        '10,10' => 'ninth cousin',
163);
164
165Readonly::Hash my %EN_FEMALE_RELATIONSHIPS => (
166        '0,0' => 'self',
167        '0,1' => 'daughter',
168        '0,2' => 'granddaughter',
169        '0,3' => 'great-granddaughter',
170        '0,4' => 'great-great-granddaughter',
171        '0,5' => 'great-great-great-granddaughter',
172        '0,6' => 'great-great-great-great-granddaughter',
173        '0,7' => 'great-great-great-great-great-granddaughter',
174        '0,8' => 'great-great-great-great-great-great-granddaughter',
175        '0,9' => 'great-great-great-great-great-great-great-granddaughter',
176        '0,10' => 'great-great-great-great-great-great-great-great-granddaughter',
177        '1,0' => 'mother',
178        '1,1' => 'sister',
179        '1,2' => 'niece',
180        '1,3' => 'great-niece',
181        '1,4' => 'great-great-niece',
182        '1,5' => 'great-great-great-niece',
183        '1,6' => 'great-great-great-great-niece',
184        '1,7' => 'great-great-great-great-great-niece',
185        '1,8' => 'great-great-great-great-great-great-niece',
186        '1,9' => 'great-great-great-great-great-great-great-niece',
187        '1,10' => 'great-great-great-great-great-great-great-great-niece',
188        '2,0' => 'grandmother',
189        '2,1' => 'aunt',
190        '2,2' => 'first cousin',
191        '2,3' => 'first cousin once-removed',
192        '2,4' => 'first cousin twice-removed',
193        '2,5' => 'first cousin three-times-removed',
194        '2,6' => 'first cousin four-times-removed',
195        '2,7' => 'first cousin five-times-removed',
196        '2,8' => 'first cousin six-times-removed',
197        '2,9' => 'first cousin seven-times-removed',
198        '2,10' => 'first cousin eight-times-removed',
199        '3,0' => 'great-grandmother',
200        '3,1' => 'great-aunt',
201        '3,2' => 'first cousin once-removed',
202        '3,3' => 'second cousin',
203        '3,4' => 'second cousin once-removed',
204        '3,5' => 'second cousin twice-removed',
205        '3,6' => 'second cousin three-times-removed',
206        '3,7' => 'second cousin four-times-removed',
207        '3,8' => 'second cousin five-times-removed',
208        '3,9' => 'second cousin six-times-removed',
209        '3,10' => 'second cousin seven-times-removed',
210        '4,0' => 'great-great-grandmother',
211        '4,1' => 'great-great-aunt',
212        '4,2' => 'first cousin twice-removed',
213        '4,3' => 'second cousin once-removed',
214        '4,4' => 'third cousin',
215        '4,5' => 'third cousin once-removed',
216        '4,6' => 'third cousin twice-removed',
217        '4,7' => 'third cousin three-times-removed',
218        '4,8' => 'third cousin four-times-removed',
219        '4,9' => 'third cousin five-times-removed',
220        '4,10' => 'third cousin six-times-removed',
221        '5,0' => 'great-great-great-grandmother',
222        '5,1' => 'great-great-great-aunt',
223        '5,2' => 'first cousin three-times-removed',
224        '5,3' => 'second cousin twice-removed',
225        '5,4' => 'third cousin once-removed',
226        '5,5' => 'fourth cousin',
227        '5,6' => 'fourth cousin once-removed',
228        '5,7' => 'fourth cousin twice-removed',
229        '5,8' => 'fourth cousin three-times-removed',
230        '5,9' => 'fourth cousin four-times-removed',
231        '5,10' => 'fourth cousin five-times-removed',
232        '6,0' => 'great-great-great-great-grandmother',
233        '6,1' => 'great-great-great-great-aunt',
234        '6,2' => 'first cousin four-times-removed',
235        '6,3' => 'second cousin three-times-removed',
236        '6,4' => 'third cousin twice-removed',
237        '6,5' => 'fourth cousin once-removed',
238        '6,6' => 'fifth cousin',
239        '6,7' => 'fifth cousin once-removed',
240        '6,8' => 'fifth cousin twice-removed',
241        '6,9' => 'fifth cousin three-times-removed',
242        '6,10' => 'fifth cousin four-times-removed',
243        '7,0' => 'great-great-great-great-great-grandmother',
244        '7,1' => 'great-great-great-great-great-aunt',
245        '7,2' => 'first cousin five-times-removed',
246        '7,3' => 'second cousin four-times-removed',
247        '7,4' => 'third cousin three-times-removed',
248        '7,5' => 'fourth cousin twice-removed',
249        '7,6' => 'fifth cousin once-removed',
250        '7,7' => 'sixth cousin',
251        '7,8' => 'sixth cousin once-removed',
252        '7,9' => 'sixth cousin twice-removed',
253        '7,10' => 'sixth cousin three-times-removed',
254        '8,0' => 'great-great-great-great-great-great-grandmother',
255        '8,1' => 'great-great-great-great-great-great-aunt',
256        '8,2' => 'first cousin six-times-removed',
257        '8,3' => 'second cousin five-times-removed',
258        '8,4' => 'third cousin four-times-removed',
259        '8,5' => 'fourth cousin three-times-removed',
260        '8,6' => 'fifth cousin twice-removed',
261        '8,7' => 'sixth cousin once-removed',
262        '8,8' => 'seventh cousin',
263        '8,9' => 'seventh cousin once-removed',
264        '8,10' => 'seventh cousin twice-removed',
265        '9,0' => 'great-great-great-great-great-great-great-grandmother',
266        '9,1' => 'great-great-great-great-great-great-great-aunt',
267        '9,2' => 'first cousin seven-times-removed',
268        '9,3' => 'second cousin six-times-removed',
269        '9,4' => 'third cousin five-times-removed',
270        '9,5' => 'fourth cousin four-times-removed',
271        '9,6' => 'fifth cousin three-times-removed',
272        '9,7' => 'sixth cousin twice-removed',
273        '9,8' => 'seventh cousin once-removed',
274        '9,9' => 'eighth cousin',
275        '9,10' => 'eighth cousin once-removed',
276        '10,0' => 'great-great-great-great-great-great-great-great-grandmother',
277        '10,1' => 'great-great-great-great-great-great-great-great-aunt',
278        '10,2' => 'first cousin eight-times-removed',
279        '10,3' => 'second cousin seven-times-removed',
280        '10,4' => 'third cousin six-times-removed',
281        '10,5' => 'fourth cousin five-times-removed',
282        '10,6' => 'fifth cousin four-times-removed',
283        '10,7' => 'sixth cousin three-times-removed',
284        '10,8' => 'seventh cousin twice-removed',
285        '10,9' => 'eighth cousin once-removed',
286        '10,10' => 'ninth cousin',
287);
288
289# ---------------------------------------------------------------------------
290# French relationship tables
291# ---------------------------------------------------------------------------
292
293Readonly::Hash my %FR_MALE_RELATIONSHIPS => (
294        '0,0' => 'soi-meme',
295        '0,1' => 'fils',
296        '0,2' => 'petit-fils',
297        '0,3' => 'arriere-petit-fils',
298        '0,4' => 'arriere-arriere-petit-fils',
299        '0,5' => 'arriere-arriere-arriere-petit-fils',
300        '0,6' => 'arriere-arriere-arriere-arriere-petit-fils',
301        '0,7' => 'arriere-arriere-arriere-arriere-arriere-petit-fils',
302        '0,8' => 'arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
303        '0,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
304        '0,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
305        '1,0' => 'pere',
306        '1,1' => "fr\N{U+00E8}re",
307        '1,2' => 'neveu',
308        '1,3' => 'grand-neveu',
309        '1,4' => 'arriere-grand-neveu',
310        '1,5' => 'arriere-arriere-grand-neveu',
311        '1,6' => 'arriere-arriere-arriere-grand-neveu',
312        '1,7' => 'arriere-arriere-arriere-arriere-grand-neveu',
313        '1,8' => 'arriere-arriere-arriere-arriere-arriere-grand-neveu',
314        '1,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-neveu',
315        '1,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-neveu',
316        '2,0' => 'grand-pere',
317        '2,1' => 'oncle',
318        '2,2' => 'cousin germain',
319        '2,3' => "cousin germain \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
320        '2,4' => 'cousin germain deux fois eloigne',
321        '2,5' => 'cousin germain trois fois eloigne',
322        '2,6' => 'cousin germain quatre fois eloigne',
323        '2,7' => 'cousin germain cinq fois eloigne',
324        '2,8' => 'cousin germain six fois eloigne',
325        '2,9' => 'cousin germain sept fois eloigne',
326        '2,10' => 'cousin germain huit fois eloigne',
327        '3,0' => 'arriere-grand-pere',
328        '3,1' => 'grand-oncle',
329        '3,2' => 'cousin germain une fois eloigne',
330        '3,2' => "cousin germain \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
331        '3,3' => 'cousin issu de germain',
332        '3,4' => 'cousin issu de germain une fois eloigne',
333        '3,5' => "cousin issu de germains \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
334        '3,6' => 'cousin issu de germain trois fois eloigne',
335        '3,7' => 'cousin issu de germain quatre fois eloigne',
336        '3,8' => 'cousin issu de germain cinq fois eloigne',
337        '3,9' => 'cousin issu de germain six fois eloigne',
338        '3,10' => 'cousin issu de germain sept fois eloigne',
339        '4,0' => 'arriere-arriere-grand-pere',
340        '4,1' => 'arriere-grand-oncle',
341        '4,2' => 'cousin germain deux fois eloigne',
342        '4,3' => 'cousin issu de germain une fois eloigne',
343        '4,4' => 'cousin au quatrieme degre',
344        '4,5' => 'cousin au quatrieme degre une fois eloigne',
345        '4,6' => 'cousin au quatrieme degre deux fois eloigne',
346        '4,7' => "petit-cousin \N{U+00E9}loign\N{U+00E9} au 3e degr\N{U+00E9}",
347        '4,8' => 'cousin au quatrieme degre quatre fois eloigne',
348        '4,9' => 'cousin au quatrieme degre cinq fois eloigne',
349        '4,10' => 'cousin au quatrieme degre six fois eloigne',
350        '5,0' => 'arriere-arriere-arriere-grand-pere',
351        '5,1' => 'arriere-arriere-grand-oncle',
352        '5,2' => 'cousin germain trois fois eloigne',
353        '5,3' => "cousin issu de germains \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
354        '5,4' => 'cousin au quatrieme degre une fois eloigne',
355        '5,5' => 'cousin au cinquieme degre',
356        '5,6' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
357        '5,7' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
358        '5,8' => 'cousin au cinquieme degre trois fois eloigne',
359        '5,9' => 'cousin au cinquieme degre quatre fois eloigne',
360        '5,10' => 'cousin au cinquieme degre cinq fois eloigne',
361        '6,0' => 'arriere-arriere-arriere-arriere-grand-pere',
362        '6,1' => 'arriere-arriere-arriere-grand-oncle',
363        '6,2' => 'cousin germain quatre fois eloigne',
364        '6,3' => 'cousin issu de germain trois fois eloigne',
365        '6,4' => 'cousin au quatrieme degre deux fois eloigne',
366        '6,5' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
367        '6,6' => "arri\N{U+00E8}re-arri\N{U+00E8}re-petit-cousin",
368        '6,7' => 'cousin au sixieme degre une fois eloigne',
369        '6,8' => 'cousin au sixieme degre deux fois eloigne',
370        '6,9' => 'cousin au sixieme degre trois fois eloigne',
371        '6,10' => 'cousin au sixieme degre quatre fois eloigne',
372        '7,0' => 'arriere-arriere-arriere-arriere-arriere-grand-pere',
373        '7,1' => 'arriere-arriere-arriere-arriere-grand-oncle',
374        '7,2' => 'cousin germain cinq fois eloigne',
375        '7,3' => 'cousin issu de germain quatre fois eloigne',
376        '7,4' => "petit-cousin \N{U+00E9}loign\N{U+00E9} au 3e degr\N{U+00E9}",
377        '7,5' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
378        '7,6' => 'cousin au sixieme degre une fois eloigne',
379        '7,7' => "sixi\N{U+00E8}me cousin",
380        '7,8' => "sixi\N{U+00E8}me cousin uns fois eloinge",
381        '7,9' => 'cousin au septieme degre deux fois eloigne',
382        '7,10' => 'cousin au septieme degre trois fois eloigne',
383        '8,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
384        '8,1' => 'arriere-arriere-arriere-arriere-arriere-grand-oncle',
385        '8,2' => 'cousin germain six fois eloigne',
386        '8,3' => 'cousin issu de germain cinq fois eloigne',
387        '8,4' => 'cousin au quatrieme degre quatre fois eloigne',
388        '8,5' => 'cousin au cinquieme degre trois fois eloigne',
389        '8,6' => 'cousin au sixieme degre deux fois eloigne',
390        '8,7' => "sixi\N{U+00E8}me cousin uns fois eloinge",
391        '8,8' => 'cousin au huitieme degre',
392        '8,9' => 'cousin au huitieme degre une fois eloigne',
393        '8,10' => 'cousin au huitieme degre deux fois eloigne',
394        '9,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
395        '9,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-oncle',
396        '9,2' => 'cousin germain sept fois eloigne',
397        '9,3' => 'cousin issu de germain six fois eloigne',
398        '9,4' => 'cousin au quatrieme degre cinq fois eloigne',
399        '9,5' => 'cousin au cinquieme degre quatre fois eloigne',
400        '9,6' => 'cousin au sixieme degre trois fois eloigne',
401        '9,7' => 'cousin au septieme degre deux fois eloigne',
402        '9,8' => 'cousin au huitieme degre une fois eloigne',
403        '9,9' => 'cousin au neuvieme degre',
404        '9,10' => 'cousin au neuvieme degre une fois eloigne',
405        '10,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
406        '10,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-oncle',
407        '10,2' => 'cousin germain huit fois eloigne',
408        '10,3' => 'cousin issu de germain sept fois eloigne',
409        '10,4' => 'cousin au quatrieme degre six fois eloigne',
410        '10,5' => 'cousin au cinquieme degre cinq fois eloigne',
411        '10,6' => 'cousin au sixieme degre quatre fois eloigne',
412        '10,7' => 'cousin au septieme degre trois fois eloigne',
413        '10,8' => 'cousin au huitieme degre deux fois eloigne',
414        '10,9' => 'cousin au neuvieme degre une fois eloigne',
415        '10,10' => 'cousin au dixieme degre',
416);
417
418Readonly::Hash my %FR_FEMALE_RELATIONSHIPS => (
419        '0,0' => 'soi-meme',
420        '0,1' => 'fille',
421        '0,2' => 'petite-fille',
422        '0,3' => 'arriere-petite-fille',
423        '0,4' => 'arriere-arriere-petite-fille',
424        '0,5' => 'arriere-arriere-arriere-petite-fille',
425        '0,6' => 'arriere-arriere-arriere-arriere-petite-fille',
426        '0,7' => 'arriere-arriere-arriere-arriere-arriere-petite-fille',
427        '0,8' => 'arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
428        '0,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
429        '0,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
430        '1,0' => 'mere',
431        '1,1' => "s\N{U+0153}ur",
432        '1,2' => "ni\N{U+00E8}ce",
433        '1,3' => 'grand-niece',
434        '1,4' => 'arriere-grand-niece',
435        '1,5' => 'arriere-arriere-grand-niece',
436        '1,6' => 'arriere-arriere-arriere-grand-niece',
437        '1,7' => 'arriere-arriere-arriere-arriere-grand-niece',
438        '1,8' => 'arriere-arriere-arriere-arriere-arriere-grand-niece',
439        '1,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-niece',
440        '1,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-niece',
441        '2,0' => 'grand-mere',
442        '2,1' => 'tante',
443        '2,2' => 'cousine germaine',
444        '2,3' => "cousine germaine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
445        '2,4' => 'cousine germaine deux fois eloignee',
446        '2,5' => 'cousine germaine trois fois eloignee',
447        '2,6' => 'cousine germaine quatre fois eloignee',
448        '2,7' => 'cousine germaine cinq fois eloignee',
449        '2,8' => 'cousine germaine six fois eloignee',
450        '2,9' => 'cousine germaine sept fois eloignee',
451        '2,10' => 'cousine germaine huit fois eloignee',
452        '3,0' => 'arriere-grand-mere',
453        '3,1' => 'grand-tante',
454        '3,2' => "cousine germaine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
455        '3,3' => 'cousine issue de germaine',
456        '3,4' => 'cousine issue de germaine une fois eloignee',
457        '3,5' => "cousine issue de germains \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
458        '3,6' => 'cousine issue de germaine trois fois eloignee',
459        '3,7' => 'cousine issue de germaine quatre fois eloignee',
460        '3,8' => 'cousine issue de germaine cinq fois eloignee',
461        '3,9' => 'cousine issue de germaine six fois eloignee',
462        '3,10' => 'cousine issue de germaine sept fois eloignee',
463        '4,0' => 'arriere-arriere-grand-mere',
464        '4,1' => 'arriere-grand-tante',
465        '4,2' => 'cousine germaine deux fois eloignee',
466        '4,3' => 'cousine issue de germaine une fois eloignee',
467        '4,4' => 'cousine au quatrieme degre',
468        '4,5' => 'cousine au quatrieme degre une fois eloignee',
469        '4,6' => 'cousine au quatrieme degre deux fois eloignee',
470        '4,7' => "petite-cousine \N{U+00E9}loign\N{U+00E9}e au 3e degr\N{U+00E9}",
471        '4,8' => 'cousine au quatrieme degre quatre fois eloignee',
472        '4,9' => 'cousine au quatrieme degre cinq fois eloignee',
473        '4,10' => 'cousine au quatrieme degre six fois eloignee',
474        '5,0' => 'arriere-arriere-arriere-grand-mere',
475        '5,1' => 'arriere-arriere-grand-tante',
476        '5,2' => 'cousine germaine trois fois eloignee',
477        '5,3' => "cousine issue de germains \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
478        '5,4' => 'cousine au quatrieme degre une fois eloignee',
479        '5,5' => 'cousine au cinquieme degre',
480        '5,6' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
481        '5,7' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
482        '5,8' => 'cousine au cinquieme degre trois fois eloignee',
483        '5,9' => 'cousine au cinquieme degre quatre fois eloignee',
484        '5,10' => 'cousine au cinquieme degre cinq fois eloignee',
485        '6,0' => 'arriere-arriere-arriere-arriere-grand-mere',
486        '6,1' => 'arriere-arriere-arriere-grand-tante',
487        '6,2' => 'cousine germaine quatre fois eloignee',
488        '6,3' => 'cousine issue de germaine trois fois eloignee',
489        '6,4' => 'cousine au quatrieme degre deux fois eloignee',
490        '6,6' => "arri\N{U+00E8}re-arri\N{U+00E8}re-petite-cousine",
491        '6,6' => 'cousine au sixieme degre',
492        '6,7' => 'cousine au sixieme degre une fois eloignee',
493        '6,8' => 'cousine au sixieme degre deux fois eloignee',
494        '6,9' => 'cousine au sixieme degre trois fois eloignee',
495        '6,10' => 'cousine au sixieme degre quatre fois eloignee',
496        '7,0' => 'arriere-arriere-arriere-arriere-arriere-grand-mere',
497        '7,1' => 'arriere-arriere-arriere-arriere-grand-tante',
498        '7,2' => 'cousine germaine cinq fois eloignee',
499        '7,3' => 'cousine issue de germaine quatre fois eloignee',
500        '7,4' => "petite-cousine \N{U+00E9}loign\N{U+00E9}e au 3e degr\N{U+00E9}",
501        '7,5' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
502        '7,6' => 'cousine au sixieme degre une fois eloignee',
503        '7,7' => "sixi\N{U+00E8}me cousin",
504        '7,8' => "sixi\N{U+00E8}me cousin once-removed",
505        '7,9' => 'cousine au septieme degre deux fois eloignee',
506        '7,10' => 'cousine au septieme degre trois fois eloignee',
507        '8,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
508        '8,1' => 'arriere-arriere-arriere-arriere-arriere-grand-tante',
509        '8,2' => 'cousine germaine six fois eloignee',
510        '8,3' => 'cousine issue de germaine cinq fois eloignee',
511        '8,4' => 'cousine au quatrieme degre quatre fois eloignee',
512        '8,5' => 'cousine au cinquieme degre trois fois eloignee',
513        '8,6' => 'cousine au sixieme degre deux fois eloignee',
514        '8,7' => "sixi\N{U+00E8}me cousin once-removed",
515        '8,8' => 'cousine au huitieme degre',
516        '8,9' => 'cousine au huitieme degre une fois eloignee',
517        '8,10' => 'cousine au huitieme degre deux fois eloignee',
518        '9,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
519        '9,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-tante',
520        '9,2' => 'cousine germaine sept fois eloignee',
521        '9,3' => 'cousine issue de germaine six fois eloignee',
522        '9,4' => 'cousine au quatrieme degre cinq fois eloignee',
523        '9,5' => 'cousine au cinquieme degre quatre fois eloignee',
524        '9,6' => 'cousine au sixieme degre trois fois eloignee',
525        '9,7' => 'cousine au septieme degre deux fois eloignee',
526        '9,8' => 'cousine au huitieme degre une fois eloignee',
527        '9,9' => 'cousine au neuvieme degre',
528        '9,10' => 'cousine au neuvieme degre une fois eloignee',
529        '10,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
530        '10,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-tante',
531        '10,2' => 'cousine germaine huit fois eloignee',
532        '10,3' => 'cousine issue de germaine sept fois eloignee',
533        '10,4' => 'cousine au quatrieme degre six fois eloignee',
534        '10,5' => 'cousine au cinquieme degre cinq fois eloignee',
535        '10,6' => 'cousine au sixieme degre quatre fois eloignee',
536        '10,7' => 'cousine au septieme degre trois fois eloignee',
537        '10,8' => 'cousine au huitieme degre deux fois eloignee',
538        '10,9' => 'cousine au neuvieme degre une fois eloignee',
539        '10,10' => 'cousine au dixieme degre',
540);
541
542# ---------------------------------------------------------------------------
543# German relationship tables
544# ---------------------------------------------------------------------------
545
546Readonly::Hash my %DE_MALE_RELATIONSHIPS => (
547        '0,0' => 'sich selbst',
548        '0,1' => 'Sohn',
549        '0,2' => 'Enkel',
550        '0,3' => 'Urenkel',
551        '0,4' => 'Ururenkel',
552        '0,5' => 'Urururenkel',
553        '0,6' => 'Ururururenkel',
554        '0,7' => 'Urururururenkel',
555        '0,8' => 'Ururururururenkel',
556        '0,9' => 'Urururururururenkel',
557        '0,10' => 'Ururururururururenkel',
558        '1,0' => 'Vater',
559        '1,1' => 'Bruder',
560        '1,2' => 'Neffe',
561        '1,3' => "Gro\N{U+00DF}neffe",
562        '1,4' => 'Urgrossneffe',
563        '1,5' => 'Ururgrossneffe',
564        '1,6' => 'Urururgrossneffe',
565        '1,7' => 'Ururururgrossneffe',
566        '1,8' => 'Urururururgrossneffe',
567        '1,9' => 'Ururururururgrossneffe',
568        '1,10' => 'Urururururururgrossneffe',
569        '2,0' => "Gro\N{U+00DF}vater",
570        '2,1' => 'Onkel',
571        '2,2' => 'Cousin',
572        '2,3' => 'Cousin einmal entfernt',
573        '2,4' => 'Cousin zweimal entfernt',
574        '2,5' => 'Cousin dreimal entfernt',
575        '2,6' => 'Cousin viermal entfernt',
576        '2,7' => 'Cousin fuenfmal entfernt',
577        '2,8' => 'Cousin sechsmal entfernt',
578        '2,9' => 'Cousin siebenmal entfernt',
579        '2,10' => 'Cousin achtmal entfernt',
580        '3,0' => 'Urgrossvater',
581        '3,1' => "Gro\N{U+00DF}onkel",
582        '3,2' => 'Cousin einmal entfernt',
583        '3,3' => 'Cousin zweiten Grades',
584        '3,4' => 'Cousin zweiten Grades einmal entfernt',
585        '3,5' => 'Cousin zweiten Grades zweimal entfernt',
586        '3,6' => 'Cousin zweiten Grades dreimal entfernt',
587        '3,7' => 'Cousin zweiten Grades viermal entfernt',
588        '3,8' => 'Cousin zweiten Grades fuenfmal entfernt',
589        '3,9' => 'Cousin zweiten Grades sechsmal entfernt',
590        '3,10' => 'Cousin zweiten Grades siebenmal entfernt',
591        '4,0' => 'Ururgrossvater',
592        '4,1' => 'Urgrossonkel',
593        '4,2' => 'Cousin zweimal entfernt',
594        '4,3' => 'Cousin zweiten Grades einmal entfernt',
595        '4,4' => 'Cousin dritten Grades',
596        '4,5' => 'Cousin dritten Grades einmal entfernt',
597        '4,6' => 'Cousin dritten Grades zweimal entfernt',
598        '4,7' => 'Cousin dritten Grades dreimal entfernt',
599        '4,8' => 'Cousin dritten Grades viermal entfernt',
600        '4,9' => 'Cousin dritten Grades fuenfmal entfernt',
601        '4,10' => 'Cousin dritten Grades sechsmal entfernt',
602        '5,0' => 'Urururgrossvater',
603        '5,1' => 'Ururgrossonkel',
604        '5,2' => 'Cousin dreimal entfernt',
605        '5,3' => 'Cousin zweiten Grades zweimal entfernt',
606        '5,4' => 'Cousin dritten Grades einmal entfernt',
607        '5,5' => 'Cousin vierten Grades',
608        '5,6' => 'Cousin vierten Grades einmal entfernt',
609        '5,7' => 'Cousin vierten Grades zweimal entfernt',
610        '5,8' => 'Cousin vierten Grades dreimal entfernt',
611        '5,9' => 'Cousin vierten Grades viermal entfernt',
612        '5,10' => 'Cousin vierten Grades fuenfmal entfernt',
613        '6,0' => 'Ururururgrossvater',
614        '6,1' => 'Urururgrossonkel',
615        '6,2' => 'Cousin viermal entfernt',
616        '6,3' => 'Cousin zweiten Grades dreimal entfernt',
617        '6,4' => 'Cousin dritten Grades zweimal entfernt',
618        '6,5' => 'Cousin vierten Grades einmal entfernt',
619        '6,6' => 'Cousin fuenften Grades',
620        '6,7' => 'Cousin fuenften Grades einmal entfernt',
621        '6,8' => 'Cousin fuenften Grades zweimal entfernt',
622        '6,9' => 'Cousin fuenften Grades dreimal entfernt',
623        '6,10' => 'Cousin fuenften Grades viermal entfernt',
624        '7,0' => 'Urururururgrossvater',
625        '7,1' => 'Ururururgrossonkel',
626        '7,2' => 'Cousin fuenfmal entfernt',
627        '7,3' => 'Cousin zweiten Grades viermal entfernt',
628        '7,4' => 'Cousin dritten Grades dreimal entfernt',
629        '7,5' => 'Cousin vierten Grades zweimal entfernt',
630        '7,6' => 'Cousin fuenften Grades einmal entfernt',
631        '7,7' => 'Cousin sechsten Grades',
632        '7,8' => 'Cousin sechsten Grades einmal entfernt',
633        '7,9' => 'Cousin sechsten Grades zweimal entfernt',
634        '7,10' => 'Cousin sechsten Grades dreimal entfernt',
635        '8,0' => 'Ururururururgrossvater',
636        '8,1' => 'Urururururgrossonkel',
637        '8,2' => 'Cousin sechsmal entfernt',
638        '8,3' => 'Cousin zweiten Grades fuenfmal entfernt',
639        '8,4' => 'Cousin dritten Grades viermal entfernt',
640        '8,5' => 'Cousin vierten Grades dreimal entfernt',
641        '8,6' => 'Cousin fuenften Grades zweimal entfernt',
642        '8,7' => 'Cousin sechsten Grades einmal entfernt',
643        '8,8' => 'Cousin siebten Grades',
644        '8,9' => 'Cousin siebten Grades einmal entfernt',
645        '8,10' => 'Cousin siebten Grades zweimal entfernt',
646        '9,0' => 'Urururururururgrossvater',
647        '9,1' => 'Ururururururgrossonkel',
648        '9,2' => 'Cousin siebenmal entfernt',
649        '9,3' => 'Cousin zweiten Grades sechsmal entfernt',
650        '9,4' => 'Cousin dritten Grades fuenfmal entfernt',
651        '9,5' => 'Cousin vierten Grades viermal entfernt',
652        '9,6' => 'Cousin fuenften Grades dreimal entfernt',
653        '9,7' => 'Cousin sechsten Grades zweimal entfernt',
654        '9,8' => 'Cousin siebten Grades einmal entfernt',
655        '9,9' => 'Cousin achten Grades',
656        '9,10' => 'Cousin achten Grades einmal entfernt',
657        '10,0' => 'Ururururururururgrossvater',
658        '10,1' => 'Urururururururgrossonkel',
659        '10,2' => 'Cousin achtmal entfernt',
660        '10,3' => 'Cousin zweiten Grades siebenmal entfernt',
661        '10,4' => 'Cousin dritten Grades sechsmal entfernt',
662        '10,5' => 'Cousin vierten Grades fuenfmal entfernt',
663        '10,6' => 'Cousin fuenften Grades viermal entfernt',
664        '10,7' => 'Cousin sechsten Grades dreimal entfernt',
665        '10,8' => 'Cousin siebten Grades zweimal entfernt',
666        '10,9' => 'Cousin achten Grades einmal entfernt',
667        '10,10' => 'Cousin neunten Grades',
668);
669
670Readonly::Hash my %DE_FEMALE_RELATIONSHIPS => (
671        '0,0' => 'sich selbst',
672        '0,1' => 'Tochter',
673        '0,2' => 'Enkelin',
674        '0,3' => 'Urenkelin',
675        '0,4' => 'Ururenkelin',
676        '0,5' => 'Urururenkelin',
677        '0,6' => 'Ururururenkelin',
678        '0,7' => 'Urururururenkelin',
679        '0,8' => 'Ururururururenkelin',
680        '0,9' => 'Urururururururenkelin',
681        '0,10' => 'Ururururururururenkelin',
682        '1,0' => 'Mutter',
683        '1,1' => 'Schwester',
684        '1,2' => 'Nichte',
685        '1,3' => "Gro\N{U+00DF}nichte",
686        '1,4' => 'Urgrossnichte',
687        '1,5' => 'Ururgrossnichte',
688        '1,6' => 'Urururgrossnichte',
689        '1,7' => 'Ururururgrossnichte',
690        '1,8' => 'Urururururgrossnichte',
691        '1,9' => 'Ururururururgrossnichte',
692        '1,10' => 'Urururururururgrossnichte',
693        '2,0' => "Gro\N{U+00DF}mutter",
694        '2,1' => 'Tante',
695        '2,2' => 'Cousine',
696        '2,3' => 'Cousine einmal entfernt',
697        '2,4' => 'Cousine zweimal entfernt',
698        '2,5' => 'Cousine dreimal entfernt',
699        '2,6' => 'Cousine viermal entfernt',
700        '2,7' => 'Cousine fuenfmal entfernt',
701        '2,8' => 'Cousine sechsmal entfernt',
702        '2,9' => 'Cousine siebenmal entfernt',
703        '2,10' => 'Cousine achtmal entfernt',
704        '3,0' => 'Urgrossmutter',
705        '3,1' => "Gro\N{U+00DF}tante",
706        '3,2' => 'Cousine einmal entfernt',
707        '3,3' => 'Cousine zweiten Grades',
708        '3,4' => 'Cousine zweiten Grades einmal entfernt',
709        '3,5' => 'Cousine zweiten Grades zweimal entfernt',
710        '3,6' => 'Cousine zweiten Grades dreimal entfernt',
711        '3,7' => 'Cousine zweiten Grades viermal entfernt',
712        '3,8' => 'Cousine zweiten Grades fuenfmal entfernt',
713        '3,9' => 'Cousine zweiten Grades sechsmal entfernt',
714        '3,10' => 'Cousine zweiten Grades siebenmal entfernt',
715        '4,0' => 'Ururgrossmutter',
716        '4,1' => 'Urgrosstante',
717        '4,2' => 'Cousine zweimal entfernt',
718        '4,3' => 'Cousine zweiten Grades einmal entfernt',
719        '4,4' => 'Cousine dritten Grades',
720        '4,5' => 'Cousine dritten Grades einmal entfernt',
721        '4,6' => 'Cousine dritten Grades zweimal entfernt',
722        '4,7' => 'Cousine dritten Grades dreimal entfernt',
723        '4,8' => 'Cousine dritten Grades viermal entfernt',
724        '4,9' => 'Cousine dritten Grades fuenfmal entfernt',
725        '4,10' => 'Cousine dritten Grades sechsmal entfernt',
726        '5,0' => 'Urururgrossmutter',
727        '5,1' => 'Ururgrosstante',
728        '5,2' => 'Cousine dreimal entfernt',
729        '5,3' => 'Cousine zweiten Grades zweimal entfernt',
730        '5,4' => 'Cousine dritten Grades einmal entfernt',
731        '5,5' => 'Cousine vierten Grades',
732        '5,6' => 'Cousine vierten Grades einmal entfernt',
733        '5,7' => 'Cousine vierten Grades zweimal entfernt',
734        '5,8' => 'Cousine vierten Grades dreimal entfernt',
735        '5,9' => 'Cousine vierten Grades viermal entfernt',
736        '5,10' => 'Cousine vierten Grades fuenfmal entfernt',
737        '6,0' => 'Ururururgrossmutter',
738        '6,1' => 'Urururgrosstante',
739        '6,2' => 'Cousine viermal entfernt',
740        '6,3' => 'Cousine zweiten Grades dreimal entfernt',
741        '6,4' => 'Cousine dritten Grades zweimal entfernt',
742        '6,5' => 'Cousine vierten Grades einmal entfernt',
743        '6,6' => 'Cousine fuenften Grades',
744        '6,7' => 'Cousine fuenften Grades einmal entfernt',
745        '6,8' => 'Cousine fuenften Grades zweimal entfernt',
746        '6,9' => 'Cousine fuenften Grades dreimal entfernt',
747        '6,10' => 'Cousine fuenften Grades viermal entfernt',
748        '7,0' => 'Urururururgrossmutter',
749        '7,1' => 'Ururururgrosstante',
750        '7,2' => 'Cousine fuenfmal entfernt',
751        '7,3' => 'Cousine zweiten Grades viermal entfernt',
752        '7,4' => 'Cousine dritten Grades dreimal entfernt',
753        '7,5' => 'Cousine vierten Grades zweimal entfernt',
754        '7,6' => 'Cousine fuenften Grades einmal entfernt',
755        '7,7' => 'Cousine sechsten Grades',
756        '7,8' => 'Cousine sechsten Grades einmal entfernt',
757        '7,9' => 'Cousine sechsten Grades zweimal entfernt',
758        '7,10' => 'Cousine sechsten Grades dreimal entfernt',
759        '8,0' => 'Ururururururgrossmutter',
760        '8,1' => 'Urururururgrosstante',
761        '8,2' => 'Cousine sechsmal entfernt',
762        '8,3' => 'Cousine zweiten Grades fuenfmal entfernt',
763        '8,4' => 'Cousine dritten Grades viermal entfernt',
764        '8,5' => 'Cousine vierten Grades dreimal entfernt',
765        '8,6' => 'Cousine fuenften Grades zweimal entfernt',
766        '8,7' => 'Cousine sechsten Grades einmal entfernt',
767        '8,8' => 'Cousine siebten Grades',
768        '8,9' => 'Cousine siebten Grades einmal entfernt',
769        '8,10' => 'Cousine siebten Grades zweimal entfernt',
770        '9,0' => 'Urururururururgrossmutter',
771        '9,1' => 'Ururururururgrosstante',
772        '9,2' => 'Cousine siebenmal entfernt',
773        '9,3' => 'Cousine zweiten Grades sechsmal entfernt',
774        '9,4' => 'Cousine dritten Grades fuenfmal entfernt',
775        '9,5' => 'Cousine vierten Grades viermal entfernt',
776        '9,6' => 'Cousine fuenften Grades dreimal entfernt',
777        '9,7' => 'Cousine sechsten Grades zweimal entfernt',
778        '9,8' => 'Cousine siebten Grades einmal entfernt',
779        '9,9' => 'Cousine achten Grades',
780        '9,10' => 'Cousine achten Grades einmal entfernt',
781        '10,0' => 'Ururururururururgrossmutter',
782        '10,1' => 'Urururururururgrosstante',
783        '10,2' => 'Cousine achtmal entfernt',
784        '10,3' => 'Cousine zweiten Grades siebenmal entfernt',
785        '10,4' => 'Cousine dritten Grades sechsmal entfernt',
786        '10,5' => 'Cousine vierten Grades fuenfmal entfernt',
787        '10,6' => 'Cousine fuenften Grades viermal entfernt',
788        '10,7' => 'Cousine sechsten Grades dreimal entfernt',
789        '10,8' => 'Cousine siebten Grades zweimal entfernt',
790        '10,9' => 'Cousine achten Grades einmal entfernt',
791        '10,10' => 'Cousine neunten Grades',
792);
793
794# ---------------------------------------------------------------------------
795# Swiss German (de-CH) relationship tables
796# Uses 'ss' instead of Eszett (\N{U+00DF}); Switzerland abolished ß in 1934
797# ---------------------------------------------------------------------------
798
799Readonly::Hash my %DE_CH_MALE_RELATIONSHIPS => (
800        '0,0' => 'sich selbst',
801        '0,1' => 'Sohn',
802        '0,2' => 'Enkel',
803        '0,3' => 'Urenkel',
804        '0,4' => 'Ururenkel',
805        '0,5' => 'Urururenkel',
806        '0,6' => 'Ururururenkel',
807        '0,7' => 'Urururururenkel',
808        '0,8' => 'Ururururururenkel',
809        '0,9' => 'Urururururururenkel',
810        '0,10' => 'Ururururururururenkel',
811        '1,0' => 'Vater',
812        '1,1' => 'Bruder',
813        '1,2' => 'Neffe',
814        '1,3' => 'Grossneffe',
815        '1,4' => 'Urgrossneffe',
816        '1,5' => 'Ururgrossneffe',
817        '1,6' => 'Urururgrossneffe',
818        '1,7' => 'Ururururgrossneffe',
819        '1,8' => 'Urururururgrossneffe',
820        '1,9' => 'Ururururururgrossneffe',
821        '1,10' => 'Urururururururgrossneffe',
822        '2,0' => 'Grossvater',
823        '2,1' => 'Onkel',
824        '2,2' => 'Cousin',
825        '2,3' => 'Cousin einmal entfernt',
826        '2,4' => 'Cousin zweimal entfernt',
827        '2,5' => 'Cousin dreimal entfernt',
828        '2,6' => 'Cousin viermal entfernt',
829        '2,7' => 'Cousin fuenfmal entfernt',
830        '2,8' => 'Cousin sechsmal entfernt',
831        '2,9' => 'Cousin siebenmal entfernt',
832        '2,10' => 'Cousin achtmal entfernt',
833        '3,0' => 'Urgrossvater',
834        '3,1' => 'Grossonkel',
835        '3,2' => 'Cousin einmal entfernt',
836        '3,3' => 'Cousin zweiten Grades',
837        '3,4' => 'Cousin zweiten Grades einmal entfernt',
838        '3,5' => 'Cousin zweiten Grades zweimal entfernt',
839        '3,6' => 'Cousin zweiten Grades dreimal entfernt',
840        '3,7' => 'Cousin zweiten Grades viermal entfernt',
841        '3,8' => 'Cousin zweiten Grades fuenfmal entfernt',
842        '3,9' => 'Cousin zweiten Grades sechsmal entfernt',
843        '3,10' => 'Cousin zweiten Grades siebenmal entfernt',
844        '4,0' => 'Ururgrossvater',
845        '4,1' => 'Urgrossonkel',
846        '4,2' => 'Cousin zweimal entfernt',
847        '4,3' => 'Cousin zweiten Grades einmal entfernt',
848        '4,4' => 'Cousin dritten Grades',
849        '4,5' => 'Cousin dritten Grades einmal entfernt',
850        '4,6' => 'Cousin dritten Grades zweimal entfernt',
851        '4,7' => 'Cousin dritten Grades dreimal entfernt',
852        '4,8' => 'Cousin dritten Grades viermal entfernt',
853        '4,9' => 'Cousin dritten Grades fuenfmal entfernt',
854        '4,10' => 'Cousin dritten Grades sechsmal entfernt',
855        '5,0' => 'Urururgrossvater',
856        '5,1' => 'Ururgrossonkel',
857        '5,2' => 'Cousin dreimal entfernt',
858        '5,3' => 'Cousin zweiten Grades zweimal entfernt',
859        '5,4' => 'Cousin dritten Grades einmal entfernt',
860        '5,5' => 'Cousin vierten Grades',
861        '5,6' => 'Cousin vierten Grades einmal entfernt',
862        '5,7' => 'Cousin vierten Grades zweimal entfernt',
863        '5,8' => 'Cousin vierten Grades dreimal entfernt',
864        '5,9' => 'Cousin vierten Grades viermal entfernt',
865        '5,10' => 'Cousin vierten Grades fuenfmal entfernt',
866        '6,0' => 'Ururururgrossvater',
867        '6,1' => 'Urururgrossonkel',
868        '6,2' => 'Cousin viermal entfernt',
869        '6,3' => 'Cousin zweiten Grades dreimal entfernt',
870        '6,4' => 'Cousin dritten Grades zweimal entfernt',
871        '6,5' => 'Cousin vierten Grades einmal entfernt',
872        '6,6' => 'Cousin fuenften Grades',
873        '6,7' => 'Cousin fuenften Grades einmal entfernt',
874        '6,8' => 'Cousin fuenften Grades zweimal entfernt',
875        '6,9' => 'Cousin fuenften Grades dreimal entfernt',
876        '6,10' => 'Cousin fuenften Grades viermal entfernt',
877        '7,0' => 'Urururururgrossvater',
878        '7,1' => 'Ururururgrossonkel',
879        '7,2' => 'Cousin fuenfmal entfernt',
880        '7,3' => 'Cousin zweiten Grades viermal entfernt',
881        '7,4' => 'Cousin dritten Grades dreimal entfernt',
882        '7,5' => 'Cousin vierten Grades zweimal entfernt',
883        '7,6' => 'Cousin fuenften Grades einmal entfernt',
884        '7,7' => 'Cousin sechsten Grades',
885        '7,8' => 'Cousin sechsten Grades einmal entfernt',
886        '7,9' => 'Cousin sechsten Grades zweimal entfernt',
887        '7,10' => 'Cousin sechsten Grades dreimal entfernt',
888        '8,0' => 'Ururururururgrossvater',
889        '8,1' => 'Urururururgrossonkel',
890        '8,2' => 'Cousin sechsmal entfernt',
891        '8,3' => 'Cousin zweiten Grades fuenfmal entfernt',
892        '8,4' => 'Cousin dritten Grades viermal entfernt',
893        '8,5' => 'Cousin vierten Grades dreimal entfernt',
894        '8,6' => 'Cousin fuenften Grades zweimal entfernt',
895        '8,7' => 'Cousin sechsten Grades einmal entfernt',
896        '8,8' => 'Cousin siebten Grades',
897        '8,9' => 'Cousin siebten Grades einmal entfernt',
898        '8,10' => 'Cousin siebten Grades zweimal entfernt',
899        '9,0' => 'Urururururururgrossvater',
900        '9,1' => 'Ururururururgrossonkel',
901        '9,2' => 'Cousin siebenmal entfernt',
902        '9,3' => 'Cousin zweiten Grades sechsmal entfernt',
903        '9,4' => 'Cousin dritten Grades fuenfmal entfernt',
904        '9,5' => 'Cousin vierten Grades viermal entfernt',
905        '9,6' => 'Cousin fuenften Grades dreimal entfernt',
906        '9,7' => 'Cousin sechsten Grades zweimal entfernt',
907        '9,8' => 'Cousin siebten Grades einmal entfernt',
908        '9,9' => 'Cousin achten Grades',
909        '9,10' => 'Cousin achten Grades einmal entfernt',
910        '10,0' => 'Ururururururururgrossvater',
911        '10,1' => 'Urururururururgrossonkel',
912        '10,2' => 'Cousin achtmal entfernt',
913        '10,3' => 'Cousin zweiten Grades siebenmal entfernt',
914        '10,4' => 'Cousin dritten Grades sechsmal entfernt',
915        '10,5' => 'Cousin vierten Grades fuenfmal entfernt',
916        '10,6' => 'Cousin fuenften Grades viermal entfernt',
917        '10,7' => 'Cousin sechsten Grades dreimal entfernt',
918        '10,8' => 'Cousin siebten Grades zweimal entfernt',
919        '10,9' => 'Cousin achten Grades einmal entfernt',
920        '10,10' => 'Cousin neunten Grades',
921);
922
923Readonly::Hash my %DE_CH_FEMALE_RELATIONSHIPS => (
924        '0,0' => 'sich selbst',
925        '0,1' => 'Tochter',
926        '0,2' => 'Enkelin',
927        '0,3' => 'Urenkelin',
928        '0,4' => 'Ururenkelin',
929        '0,5' => 'Urururenkelin',
930        '0,6' => 'Ururururenkelin',
931        '0,7' => 'Urururururenkelin',
932        '0,8' => 'Ururururururenkelin',
933        '0,9' => 'Urururururururenkelin',
934        '0,10' => 'Ururururururururenkelin',
935        '1,0' => 'Mutter',
936        '1,1' => 'Schwester',
937        '1,2' => 'Nichte',
938        '1,3' => 'Grossnichte',
939        '1,4' => 'Urgrossnichte',
940        '1,5' => 'Ururgrossnichte',
941        '1,6' => 'Urururgrossnichte',
942        '1,7' => 'Ururururgrossnichte',
943        '1,8' => 'Urururururgrossnichte',
944        '1,9' => 'Ururururururgrossnichte',
945        '1,10' => 'Urururururururgrossnichte',
946        '2,0' => 'Grossmutter',
947        '2,1' => 'Tante',
948        '2,2' => 'Cousine',
949        '2,3' => 'Cousine einmal entfernt',
950        '2,4' => 'Cousine zweimal entfernt',
951        '2,5' => 'Cousine dreimal entfernt',
952        '2,6' => 'Cousine viermal entfernt',
953        '2,7' => 'Cousine fuenfmal entfernt',
954        '2,8' => 'Cousine sechsmal entfernt',
955        '2,9' => 'Cousine siebenmal entfernt',
956        '2,10' => 'Cousine achtmal entfernt',
957        '3,0' => 'Urgrossmutter',
958        '3,1' => 'Grosstante',
959        '3,2' => 'Cousine einmal entfernt',
960        '3,3' => 'Cousine zweiten Grades',
961        '3,4' => 'Cousine zweiten Grades einmal entfernt',
962        '3,5' => 'Cousine zweiten Grades zweimal entfernt',
963        '3,6' => 'Cousine zweiten Grades dreimal entfernt',
964        '3,7' => 'Cousine zweiten Grades viermal entfernt',
965        '3,8' => 'Cousine zweiten Grades fuenfmal entfernt',
966        '3,9' => 'Cousine zweiten Grades sechsmal entfernt',
967        '3,10' => 'Cousine zweiten Grades siebenmal entfernt',
968        '4,0' => 'Ururgrossmutter',
969        '4,1' => 'Urgrosstante',
970        '4,2' => 'Cousine zweimal entfernt',
971        '4,3' => 'Cousine zweiten Grades einmal entfernt',
972        '4,4' => 'Cousine dritten Grades',
973        '4,5' => 'Cousine dritten Grades einmal entfernt',
974        '4,6' => 'Cousine dritten Grades zweimal entfernt',
975        '4,7' => 'Cousine dritten Grades dreimal entfernt',
976        '4,8' => 'Cousine dritten Grades viermal entfernt',
977        '4,9' => 'Cousine dritten Grades fuenfmal entfernt',
978        '4,10' => 'Cousine dritten Grades sechsmal entfernt',
979        '5,0' => 'Urururgrossmutter',
980        '5,1' => 'Ururgrosstante',
981        '5,2' => 'Cousine dreimal entfernt',
982        '5,3' => 'Cousine zweiten Grades zweimal entfernt',
983        '5,4' => 'Cousine dritten Grades einmal entfernt',
984        '5,5' => 'Cousine vierten Grades',
985        '5,6' => 'Cousine vierten Grades einmal entfernt',
986        '5,7' => 'Cousine vierten Grades zweimal entfernt',
987        '5,8' => 'Cousine vierten Grades dreimal entfernt',
988        '5,9' => 'Cousine vierten Grades viermal entfernt',
989        '5,10' => 'Cousine vierten Grades fuenfmal entfernt',
990        '6,0' => 'Ururururgrossmutter',
991        '6,1' => 'Urururgrosstante',
992        '6,2' => 'Cousine viermal entfernt',
993        '6,3' => 'Cousine zweiten Grades dreimal entfernt',
994        '6,4' => 'Cousine dritten Grades zweimal entfernt',
995        '6,5' => 'Cousine vierten Grades einmal entfernt',
996        '6,6' => 'Cousine fuenften Grades',
997        '6,7' => 'Cousine fuenften Grades einmal entfernt',
998        '6,8' => 'Cousine fuenften Grades zweimal entfernt',
999        '6,9' => 'Cousine fuenften Grades dreimal entfernt',
1000        '6,10' => 'Cousine fuenften Grades viermal entfernt',
1001        '7,0' => 'Urururururgrossmutter',
1002        '7,1' => 'Ururururgrosstante',
1003        '7,2' => 'Cousine fuenfmal entfernt',
1004        '7,3' => 'Cousine zweiten Grades viermal entfernt',
1005        '7,4' => 'Cousine dritten Grades dreimal entfernt',
1006        '7,5' => 'Cousine vierten Grades zweimal entfernt',
1007        '7,6' => 'Cousine fuenften Grades einmal entfernt',
1008        '7,7' => 'Cousine sechsten Grades',
1009        '7,8' => 'Cousine sechsten Grades einmal entfernt',
1010        '7,9' => 'Cousine sechsten Grades zweimal entfernt',
1011        '7,10' => 'Cousine sechsten Grades dreimal entfernt',
1012        '8,0' => 'Ururururururgrossmutter',
1013        '8,1' => 'Urururururgrosstante',
1014        '8,2' => 'Cousine sechsmal entfernt',
1015        '8,3' => 'Cousine zweiten Grades fuenfmal entfernt',
1016        '8,4' => 'Cousine dritten Grades viermal entfernt',
1017        '8,5' => 'Cousine vierten Grades dreimal entfernt',
1018        '8,6' => 'Cousine fuenften Grades zweimal entfernt',
1019        '8,7' => 'Cousine sechsten Grades einmal entfernt',
1020        '8,8' => 'Cousine siebten Grades',
1021        '8,9' => 'Cousine siebten Grades einmal entfernt',
1022        '8,10' => 'Cousine siebten Grades zweimal entfernt',
1023        '9,0' => 'Urururururururgrossmutter',
1024        '9,1' => 'Ururururururgrosstante',
1025        '9,2' => 'Cousine siebenmal entfernt',
1026        '9,3' => 'Cousine zweiten Grades sechsmal entfernt',
1027        '9,4' => 'Cousine dritten Grades fuenfmal entfernt',
1028        '9,5' => 'Cousine vierten Grades viermal entfernt',
1029        '9,6' => 'Cousine fuenften Grades dreimal entfernt',
1030        '9,7' => 'Cousine sechsten Grades zweimal entfernt',
1031        '9,8' => 'Cousine siebten Grades einmal entfernt',
1032        '9,9' => 'Cousine achten Grades',
1033        '9,10' => 'Cousine achten Grades einmal entfernt',
1034        '10,0' => 'Ururururururururgrossmutter',
1035        '10,1' => 'Urururururururgrosstante',
1036        '10,2' => 'Cousine achtmal entfernt',
1037        '10,3' => 'Cousine zweiten Grades siebenmal entfernt',
1038        '10,4' => 'Cousine dritten Grades sechsmal entfernt',
1039        '10,5' => 'Cousine vierten Grades fuenfmal entfernt',
1040        '10,6' => 'Cousine fuenften Grades viermal entfernt',
1041        '10,7' => 'Cousine sechsten Grades dreimal entfernt',
1042        '10,8' => 'Cousine siebten Grades zweimal entfernt',
1043        '10,9' => 'Cousine achten Grades einmal entfernt',
1044        '10,10' => 'Cousine neunten Grades',
1045);
1046
1047# ---------------------------------------------------------------------------
1048# Spanish relationship tables
1049# ---------------------------------------------------------------------------
1050
1051Readonly::Hash my %ES_MALE_RELATIONSHIPS => (
1052        '0,0' => 'uno mismo',
1053        '0,1' => 'hijo',
1054        '0,2' => 'nieto',
1055        '0,3' => 'bisnieto',
1056        '0,4' => 'tataranieto',
1057        '0,5' => 'chozno',
1058        '0,6' => 'bisnieto quinto',
1059        '0,7' => 'descendiente lejano',
1060        '0,8' => 'descendiente lejano',
1061        '0,9' => 'descendiente lejano',
1062        '0,10' => 'descendiente lejano',
1063        '1,0' => 'padre',
1064        '1,1' => 'hermano',
1065        '1,2' => 'sobrino',
1066        '1,3' => 'sobrino nieto',
1067        '1,4' => 'sobrino bisnieto',
1068        '1,5' => 'sobrino tataranieto',
1069        '1,6' => 'sobrino lejano',
1070        '1,7' => 'sobrino lejano',
1071        '1,8' => 'sobrino lejano',
1072        '1,9' => 'sobrino lejano',
1073        '1,10' => 'sobrino lejano',
1074        '2,0' => 'abuelo',
1075        '2,1' => 'tio',
1076        '2,2' => 'primo hermano',
1077        '2,3' => 'primo hermano una vez removido',
1078        '2,4' => 'primo hermano dos veces removido',
1079        '2,5' => 'primo hermano tres veces removido',
1080        '2,6' => 'primo hermano cuatro veces removido',
1081        '2,7' => 'primo hermano cinco veces removido',
1082        '2,8' => 'primo hermano seis veces removido',
1083        '2,9' => 'primo hermano siete veces removido',
1084        '2,10' => 'primo hermano ocho veces removido',
1085        '3,0' => 'bisabuelo',
1086        '3,1' => 'tio abuelo',
1087        '3,2' => 'primo hermano una vez removido',
1088        '3,3' => 'primo segundo',
1089        '3,4' => 'primo segundo una vez removido',
1090        '3,5' => 'primo segundo dos veces removido',
1091        '3,6' => 'primo segundo tres veces removido',
1092        '3,7' => 'primo segundo cuatro veces removido',
1093        '3,8' => 'primo segundo cinco veces removido',
1094        '3,9' => 'primo segundo seis veces removido',
1095        '3,10' => 'primo segundo siete veces removido',
1096        '4,0' => 'tatarabuelo',
1097        '4,1' => 'tio bisabuelo',
1098        '4,2' => 'primo hermano dos veces removido',
1099        '4,3' => 'primo segundo una vez removido',
1100        '4,4' => 'primo tercero',
1101        '4,5' => 'primo tercero una vez removido',
1102        '4,6' => 'primo tercero dos veces removido',
1103        '4,7' => 'primo tercero tres veces removido',
1104        '4,8' => 'primo tercero cuatro veces removido',
1105        '4,9' => 'primo tercero cinco veces removido',
1106        '4,10' => 'primo tercero seis veces removido',
1107        '5,0' => 'chozno',
1108        '5,1' => 'tio tatarabuelo',
1109        '5,2' => 'primo hermano tres veces removido',
1110        '5,3' => 'primo segundo dos veces removido',
1111        '5,4' => 'primo tercero una vez removido',
1112        '5,5' => 'primo cuarto',
1113        '5,6' => 'primo cuarto una vez removido',
1114        '5,7' => 'primo cuarto dos veces removido',
1115        '5,8' => 'primo cuarto tres veces removido',
1116        '5,9' => 'primo cuarto cuatro veces removido',
1117        '5,10' => 'primo cuarto cinco veces removido',
1118        '6,0' => 'bisabuelo quinto',
1119        '6,1' => 'tio lejano',
1120        '6,2' => 'primo hermano cuatro veces removido',
1121        '6,3' => 'primo segundo tres veces removido',
1122        '6,4' => 'primo tercero dos veces removido',
1123        '6,5' => 'primo cuarto una vez removido',
1124        '6,6' => 'primo quinto',
1125        '6,7' => 'primo quinto una vez removido',
1126        '6,8' => 'primo quinto dos veces removido',
1127        '6,9' => 'primo quinto tres veces removido',
1128        '6,10' => 'primo quinto cuatro veces removido',
1129        '7,0' => 'antepasado lejano',
1130        '7,1' => 'tio lejano',
1131        '7,2' => 'primo hermano cinco veces removido',
1132        '7,3' => 'primo segundo cuatro veces removido',
1133        '7,4' => 'primo tercero tres veces removido',
1134        '7,5' => 'primo cuarto dos veces removido',
1135        '7,6' => 'primo quinto una vez removido',
1136        '7,7' => 'primo sexto',
1137        '7,8' => 'primo sexto una vez removido',
1138        '7,9' => 'primo sexto dos veces removido',
1139        '7,10' => 'primo sexto tres veces removido',
1140        '8,0' => 'antepasado lejano',
1141        '8,1' => 'tio lejano',
1142        '8,2' => 'primo hermano seis veces removido',
1143        '8,3' => 'primo segundo cinco veces removido',
1144        '8,4' => 'primo tercero cuatro veces removido',
1145        '8,5' => 'primo cuarto tres veces removido',
1146        '8,6' => 'primo quinto dos veces removido',
1147        '8,7' => 'primo sexto una vez removido',
1148        '8,8' => 'primo septimo',
1149        '8,9' => 'primo septimo una vez removido',
1150        '8,10' => 'primo septimo dos veces removido',
1151        '9,0' => 'antepasado lejano',
1152        '9,1' => 'tio lejano',
1153        '9,2' => 'primo hermano siete veces removido',
1154        '9,3' => 'primo segundo seis veces removido',
1155        '9,4' => 'primo tercero cinco veces removido',
1156        '9,5' => 'primo cuarto cuatro veces removido',
1157        '9,6' => 'primo quinto tres veces removido',
1158        '9,7' => 'primo sexto dos veces removido',
1159        '9,8' => 'primo septimo una vez removido',
1160        '9,9' => 'primo octavo',
1161        '9,10' => 'primo octavo una vez removido',
1162        '10,0' => 'antepasado lejano',
1163        '10,1' => 'tio lejano',
1164        '10,2' => 'primo hermano ocho veces removido',
1165        '10,3' => 'primo segundo siete veces removido',
1166        '10,4' => 'primo tercero seis veces removido',
1167        '10,5' => 'primo cuarto cinco veces removido',
1168        '10,6' => 'primo quinto cuatro veces removido',
1169        '10,7' => 'primo sexto tres veces removido',
1170        '10,8' => 'primo septimo dos veces removido',
1171        '10,9' => 'primo octavo una vez removido',
1172        '10,10' => 'primo noveno',
1173);
1174
1175Readonly::Hash my %ES_FEMALE_RELATIONSHIPS => (
1176        '0,0' => 'una misma',
1177        '0,1' => 'hija',
1178        '0,2' => 'nieta',
1179        '0,3' => 'bisnieta',
1180        '0,4' => 'tataranieta',
1181        '0,5' => 'chozna',
1182        '0,6' => 'bisnieta quinta',
1183        '0,7' => 'descendiente lejana',
1184        '0,8' => 'descendiente lejana',
1185        '0,9' => 'descendiente lejana',
1186        '0,10' => 'descendiente lejana',
1187        '1,0' => 'madre',
1188        '1,1' => 'hermana',
1189        '1,2' => 'sobrina',
1190        '1,3' => 'sobrina nieta',
1191        '1,4' => 'sobrina bisnieta',
1192        '1,5' => 'sobrina tataranieta',
1193        '1,6' => 'sobrina lejana',
1194        '1,7' => 'sobrina lejana',
1195        '1,8' => 'sobrina lejana',
1196        '1,9' => 'sobrina lejana',
1197        '1,10' => 'sobrina lejana',
1198        '2,0' => 'abuela',
1199        '2,1' => 'tia',
1200        '2,2' => 'prima hermana',
1201        '2,3' => 'prima hermana una vez removida',
1202        '2,4' => 'prima hermana dos veces removida',
1203        '2,5' => 'prima hermana tres veces removida',
1204        '2,6' => 'prima hermana cuatro veces removida',
1205        '2,7' => 'prima hermana cinco veces removida',
1206        '2,8' => 'prima hermana seis veces removida',
1207        '2,9' => 'prima hermana siete veces removida',
1208        '2,10' => 'prima hermana ocho veces removida',
1209        '3,0' => 'bisabuela',
1210        '3,1' => 'tia abuela',
1211        '3,2' => 'prima hermana una vez removida',
1212        '3,3' => 'prima segunda',
1213        '3,4' => 'prima segunda una vez removida',
1214        '3,5' => 'prima segunda dos veces removida',
1215        '3,6' => 'prima segunda tres veces removida',
1216        '3,7' => 'prima segunda cuatro veces removida',
1217        '3,8' => 'prima segunda cinco veces removida',
1218        '3,9' => 'prima segunda seis veces removida',
1219        '3,10' => 'prima segunda siete veces removida',
1220        '4,0' => 'tatarabuela',
1221        '4,1' => 'tia bisabuela',
1222        '4,2' => 'prima hermana dos veces removida',
1223        '4,3' => 'prima segunda una vez removida',
1224        '4,4' => 'prima tercera',
1225        '4,5' => 'prima tercera una vez removida',
1226        '4,6' => 'prima tercera dos veces removida',
1227        '4,7' => 'prima tercera tres veces removida',
1228        '4,8' => 'prima tercera cuatro veces removida',
1229        '4,9' => 'prima tercera cinco veces removida',
1230        '4,10' => 'prima tercera seis veces removida',
1231        '5,0' => 'chozna',
1232        '5,1' => 'tia tatarabuela',
1233        '5,2' => 'prima hermana tres veces removida',
1234        '5,3' => 'prima segunda dos veces removida',
1235        '5,4' => 'prima tercera una vez removida',
1236        '5,5' => 'prima cuarta',
1237        '5,6' => 'prima cuarta una vez removida',
1238        '5,7' => 'prima cuarta dos veces removida',
1239        '5,8' => 'prima cuarta tres veces removida',
1240        '5,9' => 'prima cuarta cuatro veces removida',
1241        '5,10' => 'prima cuarta cinco veces removida',
1242        '6,0' => 'bisabuela quinta',
1243        '6,1' => 'tia lejana',
1244        '6,2' => 'prima hermana cuatro veces removida',
1245        '6,3' => 'prima segunda tres veces removida',
1246        '6,4' => 'prima tercera dos veces removida',
1247        '6,5' => 'prima cuarta una vez removida',
1248        '6,6' => 'prima quinta',
1249        '6,7' => 'prima quinta una vez removida',
1250        '6,8' => 'prima quinta dos veces removida',
1251        '6,9' => 'prima quinta tres veces removida',
1252        '6,10' => 'prima quinta cuatro veces removida',
1253        '7,0' => 'antepasada lejana',
1254        '7,1' => 'tia lejana',
1255        '7,2' => 'prima hermana cinco veces removida',
1256        '7,3' => 'prima segunda cuatro veces removida',
1257        '7,4' => 'prima tercera tres veces removida',
1258        '7,5' => 'prima cuarta dos veces removida',
1259        '7,6' => 'prima quinta una vez removida',
1260        '7,7' => 'prima sexta',
1261        '7,8' => 'prima sexta una vez removida',
1262        '7,9' => 'prima sexta dos veces removida',
1263        '7,10' => 'prima sexta tres veces removida',
1264        '8,0' => 'antepasada lejana',
1265        '8,1' => 'tia lejana',
1266        '8,2' => 'prima hermana seis veces removida',
1267        '8,3' => 'prima segunda cinco veces removida',
1268        '8,4' => 'prima tercera cuatro veces removida',
1269        '8,5' => 'prima cuarta tres veces removida',
1270        '8,6' => 'prima quinta dos veces removida',
1271        '8,7' => 'prima sexta una vez removida',
1272        '8,8' => 'prima septima',
1273        '8,9' => 'prima septima una vez removida',
1274        '8,10' => 'prima septima dos veces removida',
1275        '9,0' => 'antepasada lejana',
1276        '9,1' => 'tia lejana',
1277        '9,2' => 'prima hermana siete veces removida',
1278        '9,3' => 'prima segunda seis veces removida',
1279        '9,4' => 'prima tercera cinco veces removida',
1280        '9,5' => 'prima cuarta cuatro veces removida',
1281        '9,6' => 'prima quinta tres veces removida',
1282        '9,7' => 'prima sexta dos veces removida',
1283        '9,8' => 'prima septima una vez removida',
1284        '9,9' => 'prima octava',
1285        '9,10' => 'prima octava una vez removida',
1286        '10,0' => 'antepasada lejana',
1287        '10,1' => 'tia lejana',
1288        '10,2' => 'prima hermana ocho veces removida',
1289        '10,3' => 'prima segunda siete veces removida',
1290        '10,4' => 'prima tercera seis veces removida',
1291        '10,5' => 'prima cuarta cinco veces removida',
1292        '10,6' => 'prima quinta cuatro veces removida',
1293        '10,7' => 'prima sexta tres veces removida',
1294        '10,8' => 'prima septima dos veces removida',
1295        '10,9' => 'prima octava una vez removida',
1296        '10,10' => 'prima novena',
1297);
1298
1299# ---------------------------------------------------------------------------
1300# Farsi (Persian) relationship tables
1301# Values use \N{U+XXXX} Unicode escapes (right-to-left script)
1302# Side-specific keys: "s1,s2,paternal" / "s1,s2,maternal"
1303# ---------------------------------------------------------------------------
1304
1305Readonly::Hash my %FA_MALE_RELATIONSHIPS => (
1306        '0,0' => "\N{U+062E}\N{U+0648}\N{U+062F}",
1307        '0,1' => "\N{U+067E}\N{U+0633}\N{U+0631}",
1308        '0,2' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1309        '0,3' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1310        '0,4' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1311        '0,5' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1312        '0,6' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1313        '0,7' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1314        '0,8' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1315        '0,9' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1316        '0,10' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1317        '1,0' => "\N{U+067E}\N{U+062F}\N{U+0631}",
1318        '1,1' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}",
1319        '1,2' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1320        '1,3' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1321        '1,4' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1322        '1,5' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1323        '1,6' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1324        '1,7' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1325        '1,8' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1326        '1,9' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1327        '1,10' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1328        '2,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1329        '2,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1330        '2,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1331        '2,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1332        '2,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1333        '2,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1334        '2,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1335        '2,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1336        '2,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1337        '2,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1338        '2,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1339        '3,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1340        '3,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1341        '3,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1342        '3,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1343        '3,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1344        '3,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1345        '3,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1346        '3,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1347        '3,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1348        '3,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1349        '3,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1350        '4,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1351        '4,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1352        '4,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1353        '4,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1354        '4,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1355        '4,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1356        '4,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1357        '4,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1358        '4,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1359        '4,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1360        '4,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1361        '5,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1362        '5,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1363        '5,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1364        '5,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1365        '5,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1366        '5,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1367        '5,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1368        '5,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1369        '5,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1370        '5,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1371        '5,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1372        '6,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1373        '6,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1374        '6,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1375        '6,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1376        '6,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1377        '6,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1378        '6,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1379        '6,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1380        '6,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1381        '6,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1382        '6,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1383        '7,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1384        '7,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1385        '7,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1386        '7,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1387        '7,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1388        '7,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1389        '7,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1390        '7,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1391        '7,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1392        '7,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1393        '7,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1394        '8,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1395        '8,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1396        '8,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1397        '8,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1398        '8,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1399        '8,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1400        '8,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1401        '8,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1402        '8,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1403        '8,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1404        '8,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1405        '9,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1406        '9,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1407        '9,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1408        '9,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1409        '9,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1410        '9,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1411        '9,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1412        '9,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1413        '9,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1414        '9,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1415        '9,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1416        '10,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1417        '10,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1418        '10,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1419        '10,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1420        '10,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1421        '10,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1422        '10,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1423        '10,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1424        '10,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1425        '10,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1426        '10,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1427        '2,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1428        '2,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1429        '3,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1430        '3,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1431        '4,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1432        '4,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1433        '5,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1434        '5,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1435        '6,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1436        '6,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1437        '7,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1438        '7,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1439        '8,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1440        '8,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1441        '9,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1442        '9,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1443        '10,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
1444        '10,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
1445);
1446
1447Readonly::Hash my %FA_FEMALE_RELATIONSHIPS => (
1448        '0,0' => "\N{U+062E}\N{U+0648}\N{U+062F}",
1449        '0,1' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}",
1450        '0,2' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1451        '0,3' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1452        '0,4' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1453        '0,5' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1454        '0,6' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1455        '0,7' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1456        '0,8' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1457        '0,9' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1458        '0,10' => "\N{U+0646}\N{U+0648}\N{U+0647}",
1459        '1,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}",
1460        '1,1' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}",
1461        '1,2' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1462        '1,3' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1463        '1,4' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1464        '1,5' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1465        '1,6' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1466        '1,7' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1467        '1,8' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1468        '1,9' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1469        '1,10' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}\N{U+0632}\N{U+0627}\N{U+062F}\N{U+0647}",
1470        '2,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1471        '2,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1472        '2,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1473        '2,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1474        '2,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1475        '2,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1476        '2,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1477        '2,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1478        '2,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1479        '2,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1480        '2,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1481        '3,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1482        '3,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1483        '3,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1484        '3,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1485        '3,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1486        '3,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1487        '3,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1488        '3,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1489        '3,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1490        '3,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1491        '3,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1492        '4,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1493        '4,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1494        '4,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1495        '4,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1496        '4,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1497        '4,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1498        '4,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1499        '4,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1500        '4,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1501        '4,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1502        '4,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1503        '5,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1504        '5,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1505        '5,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1506        '5,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1507        '5,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1508        '5,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1509        '5,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1510        '5,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1511        '5,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1512        '5,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1513        '5,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1514        '6,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1515        '6,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1516        '6,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1517        '6,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1518        '6,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1519        '6,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1520        '6,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1521        '6,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1522        '6,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1523        '6,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1524        '6,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1525        '7,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1526        '7,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1527        '7,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1528        '7,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1529        '7,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1530        '7,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1531        '7,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1532        '7,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1533        '7,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1534        '7,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1535        '7,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1536        '8,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1537        '8,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1538        '8,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1539        '8,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1540        '8,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1541        '8,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1542        '8,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1543        '8,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1544        '8,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1545        '8,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1546        '8,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1547        '9,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1548        '9,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1549        '9,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1550        '9,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1551        '9,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1552        '9,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1553        '9,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1554        '9,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1555        '9,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1556        '9,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1557        '9,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1558        '10,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
1559        '10,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1560        '10,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1561        '10,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1562        '10,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1563        '10,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1564        '10,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1565        '10,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1566        '10,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1567        '10,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1568        '10,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
1569        '2,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1570        '2,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1571        '3,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1572        '3,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1573        '4,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1574        '4,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1575        '5,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1576        '5,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1577        '6,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1578        '6,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1579        '7,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1580        '7,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1581        '8,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1582        '8,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1583        '9,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1584        '9,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1585        '10,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
1586        '10,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
1587);
1588
1589# ---------------------------------------------------------------------------
1590# Classical Latin relationship tables
1591# Many step-count combinations have no classical term; those keys are absent.
1592# Side-specific keys: "s1,s2,paternal" / "s1,s2,maternal"
1593# ---------------------------------------------------------------------------
1594
1595Readonly::Hash my %LA_MALE_RELATIONSHIPS => (
1596        '0,0' => 'ipse',
1597        '0,1' => 'filius',
1598        '0,2' => 'nepos',
1599        '0,3' => 'pronepos',
1600        '0,4' => 'abnepos',
1601        '0,5' => 'atnepos',
1602        '0,6' => 'trinepos',
1603        '1,0' => 'pater',
1604        '1,1' => 'frater',
1605        '1,2' => 'nepos',
1606        '2,0' => 'avus',
1607        '2,1' => 'patruus',
1608        '2,2' => 'consobrinus',
1609        '3,0' => 'proavus',
1610        '3,1' => 'patruus magnus',
1611        '4,0' => 'abavus',
1612        '4,1' => 'patruus maior',
1613        '5,0' => 'atavus',
1614        '5,1' => 'patruus maximus',
1615        '6,0' => 'tritavus',
1616        '2,1,maternal' => 'avunculus',
1617        '2,1,paternal' => 'patruus',
1618        '2,2,maternal' => 'consobrinus',
1619        '2,2,paternal' => 'patruelis',
1620        '3,1,maternal' => 'avunculus magnus',
1621        '3,1,paternal' => 'patruus magnus',
1622        '4,1,maternal' => 'avunculus maior',
1623        '4,1,paternal' => 'patruus maior',
1624        '5,1,maternal' => 'avunculus maximus',
1625        '5,1,paternal' => 'patruus maximus',
1626);
1627
1628Readonly::Hash my %LA_FEMALE_RELATIONSHIPS => (
1629        '0,0' => 'ipsa',
1630        '0,1' => 'filia',
1631        '0,2' => 'neptis',
1632        '0,3' => 'proneptis',
1633        '0,4' => 'abneptis',
1634        '0,5' => 'atneptis',
1635        '0,6' => 'trineptis',
1636        '1,0' => 'mater',
1637        '1,1' => 'soror',
1638        '1,2' => 'neptis',
1639        '2,0' => 'avia',
1640        '2,1' => 'amita',
1641        '2,2' => 'consobrina',
1642        '3,0' => 'proavia',
1643        '3,1' => 'amita magna',
1644        '4,0' => 'abavia',
1645        '4,1' => 'amita maior',
1646        '5,0' => 'atavia',
1647        '5,1' => 'amita maxima',
1648        '6,0' => 'tritavia',
1649        '2,1,maternal' => 'matertera',
1650        '2,1,paternal' => 'amita',
1651        '2,2,maternal' => 'consobrina',
1652        '2,2,paternal' => 'patruelis',
1653        '3,1,maternal' => 'matertera magna',
1654        '3,1,paternal' => 'amita magna',
1655        '4,1,maternal' => 'matertera maior',
1656        '4,1,paternal' => 'amita maior',
1657        '5,1,maternal' => 'matertera maxima',
1658        '5,1,paternal' => 'amita maxima',
1659);
1660
1661# ---------------------------------------------------------------------------
1662# Master dispatch table: lang -> sex -> hashref
1663# ---------------------------------------------------------------------------
1664
1665Readonly::Hash my %RELATIONSHIP_TABLES => (
1666        'en' => {
1667                $SEX_MALE   => \%EN_MALE_RELATIONSHIPS,
1668                $SEX_FEMALE => \%EN_FEMALE_RELATIONSHIPS,
1669        }, 'es' => {
1670                $SEX_MALE   => \%ES_MALE_RELATIONSHIPS,
1671                $SEX_FEMALE => \%ES_FEMALE_RELATIONSHIPS,
1672        }, 'fa' => {
1673                $SEX_MALE   => \%FA_MALE_RELATIONSHIPS,
1674                $SEX_FEMALE => \%FA_FEMALE_RELATIONSHIPS,
1675        }, 'fr' => {
1676                $SEX_MALE   => \%FR_MALE_RELATIONSHIPS,
1677                $SEX_FEMALE => \%FR_FEMALE_RELATIONSHIPS,
1678        }, 'de' => {
1679                $SEX_MALE   => \%DE_MALE_RELATIONSHIPS,
1680                $SEX_FEMALE => \%DE_FEMALE_RELATIONSHIPS,
1681        }, 'de_ch' => {
1682                $SEX_MALE   => \%DE_CH_MALE_RELATIONSHIPS,
1683                $SEX_FEMALE => \%DE_CH_FEMALE_RELATIONSHIPS,
1684        }, 'la' => {
1685                $SEX_MALE   => \%LA_MALE_RELATIONSHIPS,
1686                $SEX_FEMALE => \%LA_FEMALE_RELATIONSHIPS,
1687        },
1688);
1689# ---------------------------------------------------------------------------
1690# Constructor
1691# ---------------------------------------------------------------------------
1692
1693 - 1835
=head1 NAME

Genealogy::Relationship::Name - Return a genealogical relationship name from step counts

=head1 VERSION

Version 0.03

=head1 SYNOPSIS

    use Genealogy::Relationship::Name;

    my $namer = Genealogy::Relationship::Name->new();

    my $name = $namer->name(
        steps_to_ancestor   => 2,
        steps_from_ancestor => 3,
        sex                 => 'F',
    );
    # Returns 'first cousin once-removed'

    # With language
    my $name_fr = $namer->name(
        steps_to_ancestor   => 2,
        steps_from_ancestor => 2,
        sex                 => 'M',
        language            => 'fr',
    );
    # Returns 'cousin germain'

=head1 DESCRIPTION

C<Genealogy::Relationship::Name> maps a pair of step-counts (person A to common
ancestor, common ancestor to person B) plus the sex of person B and an optional
language code to a human-readable relationship name string.

The relationship tables were originally embedded in the C<gedcom> and C<ged2site>
distributions inside C<Gedcom::Individual::relationship_up()>; this module
extracts them into a reusable, installable CPAN distribution.

Supported languages: C<en> (English, default), C<de> (German), C<es> (Spanish),
C<fa> (Farsi/Persian), C<fr> (French), C<la> (Classical Latin).

=head1 METHODS

=head2 new

Constructor.  Creates and returns a blessed C<Genealogy::Relationship::Name>
object.

=head3 PURPOSE

Initialises the object with optional configuration: a default language for
subsequent C<name()> calls, and an optional L<Log::Abstraction> object to
use as the error logger.  Configuration may also be loaded from an INI-style
file via L<Object::Configure>.

=head3 ARGUMENTS

=over 4

=item C<language> (string, optional)

Default BCP-47 language tag (primary subtag only) for all C<name()> calls
on this object.  Supported values: C<en> (default), C<fr>, C<de>.  May be
overridden per-call by passing C<language> to C<name()>.

=item C<logger>

A pre-constructed loggining object.  When a required argument is
passed as C<undef> to C<name()>, the error is reported via
C<< $logger->error($msg) >> rather than C<croak>.  This allows
programs to route errors through their own
infrastructure with full C<ctx> context.

See L<Log::Abstraction> and the L</CONFIGURATION> section for the
recommended construction pattern.

=item C<config_file> (string, optional)

Path to an INI-style configuration file processed by L<Object::Configure>.
Any keys it sets may be overridden by arguments passed directly to C<new()>.

=back

=head3 RETURNS

A blessed C<Genealogy::Relationship::Name> object.

=head3 SIDE EFFECTS

Calls L<Object::Configure> C<configure()>, which may read from a
configuration file on disk if C<config_file> is supplied or if a default
configuration file exists for the class.

=head3 NOTES

L<Object::Configure> cannot handle object or coderef values (it treats
unknown scalar values as configuration file paths).  The C<logger> key is
therefore stashed before the C<configure()> call and restored afterward.
Any future object-valued constructor arguments must follow the same pattern.

=head3 EXAMPLE

    use Genealogy::Relationship::Name;
    use Log::Abstraction;

    # Minimal construction
    my $namer = Genealogy::Relationship::Name->new();

    # With a default language
    my $namer_fr = Genealogy::Relationship::Name->new(language => 'fr');

    # With a Log::Abstraction logger
    my $la = Log::Abstraction->new(
        logger => sub {
            my $args = shift;
            my $msg = $args->{ctx}
                ? $args->{ctx}->as_string() . ': ' . join('', @{$args->{message}})
                : join('', @{$args->{message}});
            complain({ message => $msg, person => $args->{ctx} });
        },
        ctx => $individual,
    );
    my $namer = Genealogy::Relationship::Name->new(language => 'en', logger => $la);

=head3 API SPECIFICATION

=head4 Input

    {
        language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
        logger   => { type => 'object', optional => 1 },
    }

=head4 Output

    {
        type  => 'object',
        class => 'Genealogy::Relationship::Name',
    }

=cut
1836
1837sub new {
1838        # Create and return a blessed object
1839
110
655368
        my $class = shift;
1840
1841        # Handle hash or hashref arguments
1842
110
172
        my $params = Params::Get::get_params(undef, \@_);
1843
1844        # Stash keys that are coderefs or objects before passing to Object::Configure,
1845        # which cannot handle them (it treats unknown scalar values as config file paths)
1846
110
1074
        my %stash;
1847
110
108
        for my $key (qw(logger)) {
1848
110
163
                next unless exists $params->{$key};
1849
11
12
                $stash{$key} = delete $params->{$key};
1850        }
1851
1852        # Load the configuration from a config file, if provided
1853
110
136
        $params = Object::Configure::configure($class, $params);
1854
1855        # Restore the stashed coderefs and objects after configure()
1856
110
110
286884
96
        @{$params}{keys %stash} = values %stash;
1857
1858        # Bless and return the object; logger/ctx/level keys from params
1859        # are stored directly and accessed via $self->{logger} etc.
1860        return bless {
1861                # Store any constructor-time config for Object::Configure compatibility
1862
110
110
74
357
                %{$params},
1863        }, ref($class) || $class;
1864}
1865
1866# ---------------------------------------------------------------------------
1867# Public method: name()
1868# ---------------------------------------------------------------------------
1869
1870 - 1992
=head2 name

Returns the name of the relationship between person A and person B.

=head3 PURPOSE

Given the number of steps from person A up to the nearest common ancestor
(C<steps_to_ancestor>) and the number of steps from that ancestor down to
person B (C<steps_from_ancestor>), plus the sex of person B and a language
code, returns a localised relationship-name string.

=head3 ARGUMENTS

=over 4

=item C<steps_to_ancestor> (integer, required)

Number of generational steps from person A up to the common ancestor.
Must be a non-negative integer.  Zero means person A I<is> the ancestor.

=item C<steps_from_ancestor> (integer, required)

Number of generational steps from the common ancestor down to person B.
Must be a non-negative integer.

=item C<sex> (string, required)

Sex of person B.  Must be C<'M'> (male) or C<'F'> (female).

=item C<language> (string, optional)

BCP-47-style language tag (only the primary subtag is used).
Supported values: C<en> (default), C<de>, C<es>, C<fa>, C<fr>, C<la>.

Note: C<fa> (Farsi/Persian) values are stored as C<\N{U+XXXX}> Unicode
escapes and render correctly in any Unicode-aware context.  C<la>
(Classical Latin) has a sparse table; many step-count combinations have
no classical term and return C<undef>.

=item C<person> (object, optional)

An optional person object (e.g. a C<Gedcom::Individual> instance) passed
through to the error handler when an error occurs.  Takes priority over the
C<ctx> set at construction time.  The handler receives it as C<ctx> (logger
path) or C<person> (on_error path), matching the C<complain()> interface
in C<gedcom>/C<ged2site>.

=item C<family_side> (string, optional)

C<'paternal'> or C<'maternal'>.  Used by languages that distinguish the
paternal from the maternal line for the same step counts.  Currently
relevant for:

=over 4

=item * C<la> (Latin) -- uncle/aunt (C<patruus>/C<avunculus>,
C<amita>/C<matertera>) and first cousin (C<patruelis>/C<consobrinus>)

=item * C<fa> (Farsi) -- uncle (C<amoo>/C<dayi>) and aunt
(C<ammeh>/C<khaleh>)

=back

When C<family_side> is not supplied, the table falls back to the generic
(non-side-specific) entry for that step-count pair.

=back

=head3 RETURNS

A string containing the relationship name, or C<undef> if the combination
is not found in the lookup table.

=head3 EXAMPLE

    my $namer = Genealogy::Relationship::Name->new();

    # Person A is the grandparent (2 steps up) of the common ancestor,
    # and person B is 3 steps below the ancestor; B is female => first cousin once-removed
    my $rel = $namer->name(
        steps_to_ancestor   => 2,
        steps_from_ancestor => 3,
        sex                 => 'F',
    );

=head3 API SPECIFICATION

=head4 Input

    {
        steps_to_ancestor   => { type => 'integer', minimum => 0 },
        steps_from_ancestor => { type => 'integer', minimum => 0 },
        sex                 => { type => 'string', memberof => ['M', 'F'] },
        language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
        # person is handled before validate_strict (PVS infers constraints from objects)
        family_side => { type => 'string', memberof => ['paternal','maternal'], optional => 1 },
    }

=head4 Output

    {
        type     => 'string',
        optional => 1,     # undef when the combination is not tabulated
    }

=head3 FORMAL SPECIFICATION

    name ______________________________________________________
    [In]  steps_to_ancestor   : N0
          steps_from_ancestor : N0
          sex                 : {M, F}
          language            : {en, es, fa, fr, de, la}?  (default en)
          person              : Object?
    [Out] result              : String | undef

    Let key      == steps_to_ancestor ++ "," ++ steps_from_ancestor
    Let side_key == key ++ "," ++ family_side  if family_side defined
    Let table    == RELATIONSHIP_TABLES(language)(sex)
    result == table(side_key)  if family_side defined and side_key in dom table
           == table(key)       if key in dom table
           == undef            otherwise

=cut
1993
1994sub name {
1995
1519
121867
        my $self = shift;
1996
1997        # Validate and extract the remaining parameters; capture the return value
1998
1519
1336
        my $args = Params::Validate::Strict::validate_strict(
1999                args   => Params::Get::get_params(undef, \@_) || {},
2000                schema => {
2001                        steps_to_ancestor   => { type => 'integer', minimum => 0 },
2002                        steps_from_ancestor => { type => 'integer', minimum => 0 },
2003                        sex                 => { type => 'string', memberof => ['M', 'F'] },
2004                        language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
2005                        person              => { type => 'object', optional => 1 },
2006                        family_side         => { type => 'string', memberof => ['paternal','maternal'],
2007                                                 optional => 1 },
2008                }
2009        );
2010
2011        # Extract individual parameters; undef means arg was given as undef, so
2012        # report via logger if set, otherwise croak
2013
1490
234771
        foreach my $arg(qw(steps_to_ancestor steps_from_ancestor sex)) {
2014
4457
2916
                if(!defined($args->{$arg})) {
2015
7
11
                        if(my $logger = $self->{logger}) {
2016
7
12
                                $logger->error("$arg not given");
2017                        }
2018
7
1187
                        croak("$arg not given");
2019                }
2020        }
2021
1483
708
        my $steps1 = $args->{steps_to_ancestor};
2022
1483
708
        my $steps2 = $args->{steps_from_ancestor};
2023
1483
705
        my $sex    = $args->{sex};
2024
1483
705
        my $person      = $args->{person};
2025
1483
674
        my $family_side = $args->{family_side};
2026
2027        # Fall back to constructor default or hard default if no per-call language given
2028
1483
1837
        my $lang = lc($args->{language} // $self->{language} // $DEFAULT_LANGUAGE);
2029
2030        # Swiss German (de-CH) maps to its own table before subtag stripping,
2031        # because it uses 'ss' where standard German uses Eszett
2032
1483
855
        if($lang eq 'de-ch') {
2033
7
3
                $lang = 'de_ch';
2034        } else {
2035                # Strip any region subtag (e.g. 'en-GB' -> 'en') after lowercasing
2036
1476
1042
                ($lang) = split /-/, $lang;
2037        }
2038
2039        # Build lookup key from the two step counts; try side-specific key first
2040        # for languages that distinguish paternal/maternal (Latin, Farsi)
2041
1483
937
        my $key      = "${steps1},${steps2}";
2042
1483
763
        my $side_key = defined($family_side) ? "${key},${family_side}" : undef;
2043
2044        # Retrieve the correct gender-specific table for the chosen language
2045
1483
1847
        my $table = $RELATIONSHIP_TABLES{$lang}{$sex};
2046
2047        # Prefer side-specific entry when family_side is given; fall back to generic key
2048        my $result = (defined($side_key) && exists $table->{$side_key})
2049                     ? $table->{$side_key}
2050
1483
7242
                     : $table->{$key};
2051
2052
1483
4349
        return $result;
2053}
2054
2055# ---------------------------------------------------------------------------
2056# Public method: supported_languages()
2057# ---------------------------------------------------------------------------
2058
2059 - 2094
=head2 supported_languages

Returns a sorted list of the language codes that the module supports.

=head3 PURPOSE

Allows calling code to enumerate the languages available for C<name()>
without hard-coding them.

=head3 ARGUMENTS

None.

=head3 RETURNS

A list (or array-ref in scalar context) of language code strings,
currently C<('de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la')>.

=head3 EXAMPLE

    my @langs = $namer->supported_languages();
    # ( 'de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la' )

=head3 API SPECIFICATION

=head4 Input

    {}   # no arguments

=head4 Output

    {
        type => ARRAYREF,   # sorted list of language codes
    }

=cut
2095
2096sub supported_languages {
2097        # Return the sorted set of keys from the master dispatch table
2098
11
986
        my @langs = sort keys %RELATIONSHIP_TABLES;
2099
11
166
        return wantarray ? @langs : \@langs;
2100}
2101
2102# ---------------------------------------------------------------------------
2103# Public method: known_sexes()
2104# ---------------------------------------------------------------------------
2105
2106 - 2144
=head2 known_sexes

Returns the list of sex codes accepted by C<name()>.

=head3 PURPOSE

Documents and exposes the set of valid C<sex> values so that callers can
validate their own input without duplicating knowledge.

=head3 ARGUMENTS

None.

=head3 RETURNS

A list (or array-ref in scalar context) of valid sex code strings: C<('F', 'M')>.

=head3 SIDE EFFECTS

None.

=head3 EXAMPLE

    my @sexes = $namer->known_sexes();
    # ( 'F', 'M' )

=head3 API SPECIFICATION

=head4 Input

    {}   # no arguments

=head4 Output

    {
        type => ARRAYREF,
    }

=cut
2145
2146sub known_sexes {
2147        # Return the two valid sex codes in sorted order
2148
10
849
        my @sexes = sort($SEX_FEMALE, $SEX_MALE);
2149
10
17
        return wantarray ? @sexes : \@sexes;
2150}
2151
21521;
2153