lib/Genealogy/Relationship/Name.pm

Structural Coverage (Approximate)

TER1 (Statement): 100.00%
TER2 (Branch): 93.75%
TER3 (LCSAJ): 100.0% (8/8)
Approximate LCSAJ segments: 17

LCSAJ Legend

โ— Covered โ€” this LCSAJ path was executed during testing.

โ— Not covered โ€” this LCSAJ path was never executed. These are the paths to focus on.

Multiple dots on a line indicate that multiple control-flow paths begin at that line. Hovering over any dot shows:

        start โ†’ end โ†’ jump
        

Uncovered paths show [NOT COVERED] in the tooltip.

Mutant Testing Legend

Survived (tests missed this) Killed (tests detected this) No mutation
    1: package 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: use strict;
   10: use warnings;
   11: use autodie qw(:all);
   12: 
   13: use Carp qw(croak carp);
   14: use Object::Configure;
   15: use Params::Get;
   16: use Params::Validate::Strict 0.31;
   17: use Readonly;
   18: 
   19: our $VERSION = '0.03';
   20: 
   21: # ---------------------------------------------------------------------------
   22: # Constants – relationship table keys
   23: # ---------------------------------------------------------------------------
   24: 
   25: # Supported language codes
   26: Readonly::Array my @SUPPORTED_LANGUAGES => qw(de de_ch en es fa fr la);
   27: 
   28: # Default language when none supplied
   29: Readonly::Scalar my $DEFAULT_LANGUAGE => 'en';
   30: 
   31: # Sex constants
   32: Readonly::Scalar my $SEX_MALE   => 'M';
   33: Readonly::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: 
   41: Readonly::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: 
  165: Readonly::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: 
  293: Readonly::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: 
  418: Readonly::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: 
  546: Readonly::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: 
  670: Readonly::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: 
  799: Readonly::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: 
  923: Readonly::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: 
 1051: Readonly::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: 
 1175: Readonly::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: 
 1305: Readonly::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: 
 1447: Readonly::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: 
 1595: Readonly::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: 
 1628: Readonly::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: 
 1665: Readonly::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: =head1 NAME
 1694: 
 1695: Genealogy::Relationship::Name - Return a genealogical relationship name from step counts
 1696: 
 1697: =head1 VERSION
 1698: 
 1699: Version 0.03
 1700: 
 1701: =head1 SYNOPSIS
 1702: 
 1703:     use Genealogy::Relationship::Name;
 1704: 
 1705:     my $namer = Genealogy::Relationship::Name->new();
 1706: 
 1707:     my $name = $namer->name(
 1708:         steps_to_ancestor   => 2,
 1709:         steps_from_ancestor => 3,
 1710:         sex                 => 'F',
 1711:     );
 1712:     # Returns 'first cousin once-removed'
 1713: 
 1714:     # With language
 1715:     my $name_fr = $namer->name(
 1716:         steps_to_ancestor   => 2,
 1717:         steps_from_ancestor => 2,
 1718:         sex                 => 'M',
 1719:         language            => 'fr',
 1720:     );
 1721:     # Returns 'cousin germain'
 1722: 
 1723: =head1 DESCRIPTION
 1724: 
 1725: C<Genealogy::Relationship::Name> maps a pair of step-counts (person A to common
 1726: ancestor, common ancestor to person B) plus the sex of person B and an optional
 1727: language code to a human-readable relationship name string.
 1728: 
 1729: The relationship tables were originally embedded in the C<gedcom> and C<ged2site>
 1730: distributions inside C<Gedcom::Individual::relationship_up()>; this module
 1731: extracts them into a reusable, installable CPAN distribution.
 1732: 
 1733: Supported languages: C<en> (English, default), C<de> (German), C<es> (Spanish),
 1734: C<fa> (Farsi/Persian), C<fr> (French), C<la> (Classical Latin).
 1735: 
 1736: =head1 METHODS
 1737: 
 1738: =head2 new
 1739: 
 1740: Constructor.  Creates and returns a blessed C<Genealogy::Relationship::Name>
 1741: object.
 1742: 
 1743: =head3 PURPOSE
 1744: 
 1745: Initialises the object with optional configuration: a default language for
 1746: subsequent C<name()> calls, and an optional L<Log::Abstraction> object to
 1747: use as the error logger.  Configuration may also be loaded from an INI-style
 1748: file via L<Object::Configure>.
 1749: 
 1750: =head3 ARGUMENTS
 1751: 
 1752: =over 4
 1753: 
 1754: =item C<language> (string, optional)
 1755: 
 1756: Default BCP-47 language tag (primary subtag only) for all C<name()> calls
 1757: on this object.  Supported values: C<en> (default), C<fr>, C<de>.  May be
 1758: overridden per-call by passing C<language> to C<name()>.
 1759: 
 1760: =item C<logger>
 1761: 
 1762: A pre-constructed loggining object.  When a required argument is
 1763: passed as C<undef> to C<name()>, the error is reported via
 1764: C<< $logger->error($msg) >> rather than C<croak>.  This allows
 1765: programs to route errors through their own
 1766: infrastructure with full C<ctx> context.
 1767: 
 1768: See L<Log::Abstraction> and the L</CONFIGURATION> section for the
 1769: recommended construction pattern.
 1770: 
 1771: =item C<config_file> (string, optional)
 1772: 
 1773: Path to an INI-style configuration file processed by L<Object::Configure>.
 1774: Any keys it sets may be overridden by arguments passed directly to C<new()>.
 1775: 
 1776: =back
 1777: 
 1778: =head3 RETURNS
 1779: 
 1780: A blessed C<Genealogy::Relationship::Name> object.
 1781: 
 1782: =head3 SIDE EFFECTS
 1783: 
 1784: Calls L<Object::Configure> C<configure()>, which may read from a
 1785: configuration file on disk if C<config_file> is supplied or if a default
 1786: configuration file exists for the class.
 1787: 
 1788: =head3 NOTES
 1789: 
 1790: L<Object::Configure> cannot handle object or coderef values (it treats
 1791: unknown scalar values as configuration file paths).  The C<logger> key is
 1792: therefore stashed before the C<configure()> call and restored afterward.
 1793: Any future object-valued constructor arguments must follow the same pattern.
 1794: 
 1795: =head3 EXAMPLE
 1796: 
 1797:     use Genealogy::Relationship::Name;
 1798:     use Log::Abstraction;
 1799: 
 1800:     # Minimal construction
 1801:     my $namer = Genealogy::Relationship::Name->new();
 1802: 
 1803:     # With a default language
 1804:     my $namer_fr = Genealogy::Relationship::Name->new(language => 'fr');
 1805: 
 1806:     # With a Log::Abstraction logger
 1807:     my $la = Log::Abstraction->new(
 1808:         logger => sub {
 1809:             my $args = shift;
 1810:             my $msg = $args->{ctx}
 1811:                 ? $args->{ctx}->as_string() . ': ' . join('', @{$args->{message}})
 1812:                 : join('', @{$args->{message}});
 1813:             complain({ message => $msg, person => $args->{ctx} });
 1814:         },
 1815:         ctx => $individual,
 1816:     );
 1817:     my $namer = Genealogy::Relationship::Name->new(language => 'en', logger => $la);
 1818: 
 1819: =head3 API SPECIFICATION
 1820: 
 1821: =head4 Input
 1822: 
 1823:     {
 1824: 	language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
 1825:         logger   => { type => 'object', optional => 1 },
 1826:     }
 1827: 
 1828: =head4 Output
 1829: 
 1830:     {
 1831:         type  => 'object',
 1832:         class => 'Genealogy::Relationship::Name',
 1833:     }
 1834: 
 1835: =cut
 1836: 
 1837: sub new {
 1838: 	# Create and return a blessed object
โ—1839 โ†’ 1847 โ†’ 1853โ—1839 โ†’ 1847 โ†’ 0 1839: 	my $class = shift;
 1840: 
 1841: 	# Handle hash or hashref arguments
 1842: 	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: 	my %stash;
 1847: 	for my $key (qw(logger)) {
 1848: 		next unless exists $params->{$key};
 1849: 		$stash{$key} = delete $params->{$key};
 1850: 	}
 1851: 
 1852: 	# Load the configuration from a config file, if provided
โ—1853 โ†’ 1860 โ†’ 0 1853: 	$params = Object::Configure::configure($class, $params);
 1854: 
 1855: 	# Restore the stashed coderefs and objects after configure()
 1856: 	@{$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: 		%{$params},
 1863: 	}, ref($class) || $class;
 1864: }
 1865: 
 1866: # ---------------------------------------------------------------------------
 1867: # Public method: name()
 1868: # ---------------------------------------------------------------------------
 1869: 
 1870: =head2 name
 1871: 
 1872: Returns the name of the relationship between person A and person B.
 1873: 
 1874: =head3 PURPOSE
 1875: 
 1876: Given the number of steps from person A up to the nearest common ancestor
 1877: (C<steps_to_ancestor>) and the number of steps from that ancestor down to
 1878: person B (C<steps_from_ancestor>), plus the sex of person B and a language
 1879: code, returns a localised relationship-name string.
 1880: 
 1881: =head3 ARGUMENTS
 1882: 
 1883: =over 4
 1884: 
 1885: =item C<steps_to_ancestor> (integer, required)
 1886: 
 1887: Number of generational steps from person A up to the common ancestor.
 1888: Must be a non-negative integer.  Zero means person A I<is> the ancestor.
 1889: 
 1890: =item C<steps_from_ancestor> (integer, required)
 1891: 
 1892: Number of generational steps from the common ancestor down to person B.
 1893: Must be a non-negative integer.
 1894: 
 1895: =item C<sex> (string, required)
 1896: 
 1897: Sex of person B.  Must be C<'M'> (male) or C<'F'> (female).
 1898: 
 1899: =item C<language> (string, optional)
 1900: 
 1901: BCP-47-style language tag (only the primary subtag is used).
 1902: Supported values: C<en> (default), C<de>, C<es>, C<fa>, C<fr>, C<la>.
 1903: 
 1904: Note: C<fa> (Farsi/Persian) values are stored as C<\N{U+XXXX}> Unicode
 1905: escapes and render correctly in any Unicode-aware context.  C<la>
 1906: (Classical Latin) has a sparse table; many step-count combinations have
 1907: no classical term and return C<undef>.
 1908: 
 1909: =item C<person> (object, optional)
 1910: 
 1911: An optional person object (e.g. a C<Gedcom::Individual> instance) passed
 1912: through to the error handler when an error occurs.  Takes priority over the
 1913: C<ctx> set at construction time.  The handler receives it as C<ctx> (logger
 1914: path) or C<person> (on_error path), matching the C<complain()> interface
 1915: in C<gedcom>/C<ged2site>.
 1916: 
 1917: =item C<family_side> (string, optional)
 1918: 
 1919: C<'paternal'> or C<'maternal'>.  Used by languages that distinguish the
 1920: paternal from the maternal line for the same step counts.  Currently
 1921: relevant for:
 1922: 
 1923: =over 4
 1924: 
 1925: =item * C<la> (Latin) -- uncle/aunt (C<patruus>/C<avunculus>,
 1926: C<amita>/C<matertera>) and first cousin (C<patruelis>/C<consobrinus>)
 1927: 
 1928: =item * C<fa> (Farsi) -- uncle (C<amoo>/C<dayi>) and aunt
 1929: (C<ammeh>/C<khaleh>)
 1930: 
 1931: =back
 1932: 
 1933: When C<family_side> is not supplied, the table falls back to the generic
 1934: (non-side-specific) entry for that step-count pair.
 1935: 
 1936: =back
 1937: 
 1938: =head3 RETURNS
 1939: 
 1940: A string containing the relationship name, or C<undef> if the combination
 1941: is not found in the lookup table.
 1942: 
 1943: =head3 EXAMPLE
 1944: 
 1945:     my $namer = Genealogy::Relationship::Name->new();
 1946: 
 1947:     # Person A is the grandparent (2 steps up) of the common ancestor,
 1948:     # and person B is 3 steps below the ancestor; B is female => first cousin once-removed
 1949:     my $rel = $namer->name(
 1950:         steps_to_ancestor   => 2,
 1951:         steps_from_ancestor => 3,
 1952:         sex                 => 'F',
 1953:     );
 1954: 
 1955: =head3 API SPECIFICATION
 1956: 
 1957: =head4 Input
 1958: 
 1959:     {
 1960: 	steps_to_ancestor   => { type => 'integer', minimum => 0 },
 1961: 	steps_from_ancestor => { type => 'integer', minimum => 0 },
 1962: 	sex                 => { type => 'string', memberof => ['M', 'F'] },
 1963:         language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
 1964: 	# person is handled before validate_strict (PVS infers constraints from objects)
 1965: 	family_side => { type => 'string', memberof => ['paternal','maternal'], optional => 1 },
 1966:     }
 1967: 
 1968: =head4 Output
 1969: 
 1970:     {
 1971:         type     => 'string',
 1972:         optional => 1,     # undef when the combination is not tabulated
 1973:     }
 1974: 
 1975: =head3 FORMAL SPECIFICATION
 1976: 
 1977:     name ______________________________________________________
 1978:     [In]  steps_to_ancestor   : N0
 1979:           steps_from_ancestor : N0
 1980:           sex                 : {M, F}
 1981:           language            : {en, es, fa, fr, de, la}?  (default en)
 1982:           person              : Object?
 1983:     [Out] result              : String | undef
 1984: 
 1985:     Let key      == steps_to_ancestor ++ "," ++ steps_from_ancestor
 1986:     Let side_key == key ++ "," ++ family_side  if family_side defined
 1987:     Let table    == RELATIONSHIP_TABLES(language)(sex)
 1988:     result == table(side_key)  if family_side defined and side_key in dom table
 1989:            == table(key)       if key in dom table
 1990:            == undef            otherwise
 1991: 
 1992: =cut
 1993: 
 1994: sub name {
โ—1995 โ†’ 2013 โ†’ 2021โ—1995 โ†’ 2013 โ†’ 0 1995: 	my $self = shift;
 1996: 
 1997: 	# Validate and extract the remaining parameters; capture the return value
 1998: 	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: 	foreach my $arg(qw(steps_to_ancestor steps_from_ancestor sex)) {
 2014: 		if(!defined($args->{$arg})) {

					
Mutants (Total: 1, Killed: 0, Survived: 1)
2015: if(my $logger = $self->{logger}) {
Mutants (Total: 1, Killed: 0, Survived: 1)
2016: $logger->error("$arg not given"); 2017: } 2018: croak("$arg not given"); 2019: } 2020: } โ—2021 โ†’ 2032 โ†’ 2041โ—2021 โ†’ 2032 โ†’ 0 2021: my $steps1 = $args->{steps_to_ancestor}; 2022: my $steps2 = $args->{steps_from_ancestor}; 2023: my $sex = $args->{sex}; 2024: my $person = $args->{person}; 2025: my $family_side = $args->{family_side}; 2026: 2027: # Fall back to constructor default or hard default if no per-call language given 2028: 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: if($lang eq 'de-ch') {
Mutants (Total: 1, Killed: 0, Survived: 1)
2033: $lang = 'de_ch'; 2034: } else { 2035: # Strip any region subtag (e.g. 'en-GB' -> 'en') after lowercasing 2036: ($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 โ†’ 2052 โ†’ 0 2041: my $key = "${steps1},${steps2}"; 2042: my $side_key = defined($family_side) ? "${key},${family_side}" : undef; 2043: 2044: # Retrieve the correct gender-specific table for the chosen language 2045: 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: : $table->{$key}; 2051: 2052: return $result;
Mutants (Total: 2, Killed: 0, Survived: 2)
2053: } 2054: 2055: # --------------------------------------------------------------------------- 2056: # Public method: supported_languages() 2057: # --------------------------------------------------------------------------- 2058: 2059: =head2 supported_languages 2060: 2061: Returns a sorted list of the language codes that the module supports. 2062: 2063: =head3 PURPOSE 2064: 2065: Allows calling code to enumerate the languages available for C<name()> 2066: without hard-coding them. 2067: 2068: =head3 ARGUMENTS 2069: 2070: None. 2071: 2072: =head3 RETURNS 2073: 2074: A list (or array-ref in scalar context) of language code strings, 2075: currently C<('de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la')>. 2076: 2077: =head3 EXAMPLE 2078: 2079: my @langs = $namer->supported_languages(); 2080: # ( 'de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la' ) 2081: 2082: =head3 API SPECIFICATION 2083: 2084: =head4 Input 2085: 2086: {} # no arguments 2087: 2088: =head4 Output 2089: 2090: { 2091: type => ARRAYREF, # sorted list of language codes 2092: } 2093: 2094: =cut 2095: 2096: sub supported_languages { 2097: # Return the sorted set of keys from the master dispatch table 2098: my @langs = sort keys %RELATIONSHIP_TABLES; 2099: return wantarray ? @langs : \@langs;
Mutants (Total: 2, Killed: 0, Survived: 2)
2100: } 2101: 2102: # --------------------------------------------------------------------------- 2103: # Public method: known_sexes() 2104: # --------------------------------------------------------------------------- 2105: 2106: =head2 known_sexes 2107: 2108: Returns the list of sex codes accepted by C<name()>. 2109: 2110: =head3 PURPOSE 2111: 2112: Documents and exposes the set of valid C<sex> values so that callers can 2113: validate their own input without duplicating knowledge. 2114: 2115: =head3 ARGUMENTS 2116: 2117: None. 2118: 2119: =head3 RETURNS 2120: 2121: A list (or array-ref in scalar context) of valid sex code strings: C<('F', 'M')>. 2122: 2123: =head3 SIDE EFFECTS 2124: 2125: None. 2126: 2127: =head3 EXAMPLE 2128: 2129: my @sexes = $namer->known_sexes(); 2130: # ( 'F', 'M' ) 2131: 2132: =head3 API SPECIFICATION 2133: 2134: =head4 Input 2135: 2136: {} # no arguments 2137: 2138: =head4 Output 2139: 2140: { 2141: type => ARRAYREF, 2142: } 2143: 2144: =cut 2145: 2146: sub known_sexes { 2147: # Return the two valid sex codes in sorted order 2148: my @sexes = sort($SEX_FEMALE, $SEX_MALE); 2149: return wantarray ? @sexes : \@sexes;
Mutants (Total: 2, Killed: 0, Survived: 2)
2150: } 2151: 2152: 1; 2153: 2154: __END__ 2155: 2156: =head1 CONFIGURATION 2157: 2158: The constructor accepts an optional C<language> key which sets the default 2159: language for all subsequent calls to C<name()>: 2160: 2161: my $namer = Genealogy::Relationship::Name->new(language => 'fr'); 2162: 2163: This default can be overridden per-call by passing C<language> to C<name()>. 2164: The object is also compatible with C<Object::Configure> for runtime 2165: reconfiguration. 2166: 2167: =head2 Error handling 2168: 2169: Errors are dispatched through the following priority chain: 2170: 2171: =over 4 2172: 2173: =item 1. L<Log::Abstraction> object (preferred) 2174: 2175: Construct a C<Log::Abstraction> object with the desired logger coderef and 2176: C<ctx> (typically a C<Gedcom::Individual>), then pass it as C<logger> to 2177: C<new()>. On error, this module simply calls C<< $logger->error($msg) >> 2178: and Log::Abstraction handles ctx forwarding, formatting, and dispatch. 2179: 2180: use Log::Abstraction; 2181: 2182: my $logger = Log::Abstraction->new( 2183: logger => sub { 2184: my $args = shift; 2185: my $msg = $args->{ctx} 2186: ? $args->{ctx}->as_string() . ': ' . join('', @{$args->{message}}) 2187: : join('', @{$args->{message}}); 2188: complain({ message => $msg, person => $args->{ctx} }); 2189: }, 2190: ctx => $individual, 2191: ); 2192: 2193: my $namer = Genealogy::Relationship::Name->new(logger => $logger); 2194: 2195: =back 2196: 2197: If any handler returns without dying (e.g. a warning-only handler in 2198: L<Log::Abstraction>), C<name()> returns C<undef>. 2199: 2200: =head1 DIAGNOSTICS 2201: 2202: =over 4 2203: 2204: =item steps_to_ancestor not given 2205: 2206: C<steps_to_ancestor> was passed as C<undef>. Passing C<undef> explicitly is 2207: distinct from omitting the argument; use a defined non-negative integer. 2208: 2209: =item steps_from_ancestor not given 2210: 2211: As above, for C<steps_from_ancestor>. 2212: 2213: =item sex not given 2214: 2215: C<sex> was passed as C<undef>. Supply C<'M'> or C<'F'>. 2216: 2217: =back 2218: 2219: =head1 DEPENDENCIES 2220: 2221: L<Carp>, L<Object::Configure> 2222: 2223: Optionally L<Log::Abstraction> (E<gt>= 0.28) for the C<logger>/C<ctx> error 2224: dispatch path. 2225: L<Params::Get>, L<Params::Validate::Strict>, L<Readonly> 2226: 2227: =head1 BUGS AND LIMITATIONS 2228: 2229: The lookup tables currently cover steps 0-6 in both directions. Relationships 2230: further removed (seventh cousin, etc.) return C<undef>. Pull requests adding 2231: deeper tables are welcome. 2232: 2233: =head1 TODO 2234: 2235: =over 4 2236: 2237: =item * Extract and integrate the Latin relationship handling code currently 2238: embedded in the C<gedcom> and C<ged2site> programs, adding C<la> as a 2239: supported language alongside C<en>, C<fr>, and C<de>. 2240: 2241: =back 2242: 2243: =head1 SEE ALSO 2244: 2245: =over 4 2246: 2247: =item * L<Configure an Object at Runtime|Object::Configure> 2248: 2249: =item * L<Test Dashboard|https://nigelhorne.github.io/Genealogy-Relationship-Name/coverage/> 2250: 2251: =item * L<Gedcom::Individual>, L<Genealogy::Relationship>, L<https://www.tfcg.ca/tableau-des-liens-de-parente>, 2252: 2253: =back 2254: 2255: =head1 AUTHOR 2256: 2257: Nigel Horne C<< <njh@nigelhorne.com> >> 2258: 2259: =head1 REPOSITORY 2260: 2261: L<https://github.com/nigelhorne/Genealogy-Relationship-Name> 2262: 2263: =head1 SUPPORT 2264: 2265: This module is provided as-is without any warranty. 2266: 2267: Please report any bugs or feature requests to C<bug-genealogy-relationship-name at rt.cpan.org>, 2268: or through the web interface at 2269: L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Genealogy-Relationship-Name>. 2270: I will be notified, and then you'll 2271: automatically be notified of progress on your bug as I make changes. 2272: 2273: You can find documentation for this module with the perldoc command. 2274: 2275: perldoc Genealogy::Relationship::Name 2276: 2277: You can also look for information at: 2278: 2279: =over 4 2280: 2281: =item * MetaCPAN 2282: 2283: L<https://metacpan.org/dist/Genealogy-Relationship-Name> 2284: 2285: =item * RT: CPAN's request tracker 2286: 2287: L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Genealogy-Relationship-Name> 2288: 2289: =item * CPAN Testers' Matrix 2290: 2291: L<http://matrix.cpantesters.org/?dist=Genealogy-Relationship-Name> 2292: 2293: =item * CPAN Testers Dependencies 2294: 2295: L<http://deps.cpantesters.org/?module=Genealogy::Relationship::Name> 2296: 2297: =back 2298: 2299: =head1 FORMAL SPECIFICATION 2300: 2301: =head2 new 2302: 2303: new ________________________________________________________ 2304: [In] class : String (class name or object) 2305: language : {en, es, fa, fr, de, la}? (optional default language 2306: logger : Log::Abstraction? (optional error logger) 2307: [Out] self : Genealogy::Relationship::Name 2308: 2309: Let params == get_params(args) 2310: Let params' == configure(class, params \ {logger}) 2311: union {logger -> params.logger} if logger in dom params 2312: self == bless(params', class) 2313: 2314: post: self.language == params.language if language in dom params 2315: self.logger == params.logger if logger in dom params 2316: ref(self) == 'Genealogy::Relationship::Name' 2317: 2318: =head2 name 2319: 2320: name ______________________________________________________ 2321: [In] steps_to_ancestor : N0 2322: steps_from_ancestor : N0 2323: sex : {M, F} 2324: language : {en, fr, de}? (default en) 2325: person : Object? 2326: [Out] result : String | undef 2327: 2328: Let key == steps_to_ancestor ++ "," ++ steps_from_ancestor 2329: Let table == RELATIONSHIP_TABLES(language)(sex) 2330: result == table(key) if key in dom table 2331: == undef otherwise 2332: 2333: =head2 supported_languages 2334: 2335: supported_languages ______________________________________ 2336: [In] (none) 2337: [Out] result : seq String 2338: 2339: result == sort(dom RELATIONSHIP_TABLES) 2340: 2341: =head2 known_sexes 2342: 2343: known_sexes ______________________________________________ 2344: [In] (none) 2345: [Out] result : seq String 2346: 2347: result == sort { $SEX_FEMALE, $SEX_MALE } 2348: 2349: =head1 LICENCE AND COPYRIGHT 2350: 2351: Copyright 2026 Nigel Horne. 2352: 2353: Usage is subject to the GPL2 licence terms. 2354: If you use it, 2355: please let me know. 2356: 2357: =cut