lib/Genealogy/Relationship/Name.pm

Structural Coverage (Approximate)

TER1 (Statement): 100.00%
TER2 (Branch): 93.75%
TER3 (LCSAJ): 100.0% (3/3)
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: 	'11,1' => 'eigth great-uncle',
  164: 	'12,1' => 'ninth great-uncle',
  165: 	'13,1' => 'tenth great-uncle',
  166: 	'16,1' => 'thirteenth great-uncle',
  167: 	'17,1' => 'fourteenth great-uncle',
  168: );
  169: 
  170: Readonly::Hash my %EN_FEMALE_RELATIONSHIPS => (
  171: 	'0,0' => 'self',
  172: 	'0,1' => 'daughter',
  173: 	'0,2' => 'granddaughter',
  174: 	'0,3' => 'great-granddaughter',
  175: 	'0,4' => 'great-great-granddaughter',
  176: 	'0,5' => 'great-great-great-granddaughter',
  177: 	'0,6' => 'great-great-great-great-granddaughter',
  178: 	'0,7' => 'great-great-great-great-great-granddaughter',
  179: 	'0,8' => 'great-great-great-great-great-great-granddaughter',
  180: 	'0,9' => 'great-great-great-great-great-great-great-granddaughter',
  181: 	'0,10' => 'great-great-great-great-great-great-great-great-granddaughter',
  182: 	'1,0' => 'mother',
  183: 	'1,1' => 'sister',
  184: 	'1,2' => 'niece',
  185: 	'1,3' => 'great-niece',
  186: 	'1,4' => 'great-great-niece',
  187: 	'1,5' => 'great-great-great-niece',
  188: 	'1,6' => 'great-great-great-great-niece',
  189: 	'1,7' => 'great-great-great-great-great-niece',
  190: 	'1,8' => 'great-great-great-great-great-great-niece',
  191: 	'1,9' => 'great-great-great-great-great-great-great-niece',
  192: 	'1,10' => 'great-great-great-great-great-great-great-great-niece',
  193: 	'2,0' => 'grandmother',
  194: 	'2,1' => 'aunt',
  195: 	'2,2' => 'first cousin',
  196: 	'2,3' => 'first cousin once-removed',
  197: 	'2,4' => 'first cousin twice-removed',
  198: 	'2,5' => 'first cousin three-times-removed',
  199: 	'2,6' => 'first cousin four-times-removed',
  200: 	'2,7' => 'first cousin five-times-removed',
  201: 	'2,8' => 'first cousin six-times-removed',
  202: 	'2,9' => 'first cousin seven-times-removed',
  203: 	'2,10' => 'first cousin eight-times-removed',
  204: 	'3,0' => 'great-grandmother',
  205: 	'3,1' => 'great-aunt',
  206: 	'3,2' => 'first cousin once-removed',
  207: 	'3,3' => 'second cousin',
  208: 	'3,4' => 'second cousin once-removed',
  209: 	'3,5' => 'second cousin twice-removed',
  210: 	'3,6' => 'second cousin three-times-removed',
  211: 	'3,7' => 'second cousin four-times-removed',
  212: 	'3,8' => 'second cousin five-times-removed',
  213: 	'3,9' => 'second cousin six-times-removed',
  214: 	'3,10' => 'second cousin seven-times-removed',
  215: 	'4,0' => 'great-great-grandmother',
  216: 	'4,1' => 'great-great-aunt',
  217: 	'4,2' => 'first cousin twice-removed',
  218: 	'4,3' => 'second cousin once-removed',
  219: 	'4,4' => 'third cousin',
  220: 	'4,5' => 'third cousin once-removed',
  221: 	'4,6' => 'third cousin twice-removed',
  222: 	'4,7' => 'third cousin three-times-removed',
  223: 	'4,8' => 'third cousin four-times-removed',
  224: 	'4,9' => 'third cousin five-times-removed',
  225: 	'4,10' => 'third cousin six-times-removed',
  226: 	'5,0' => 'great-great-great-grandmother',
  227: 	'5,1' => 'great-great-great-aunt',
  228: 	'5,2' => 'first cousin three-times-removed',
  229: 	'5,3' => 'second cousin twice-removed',
  230: 	'5,4' => 'third cousin once-removed',
  231: 	'5,5' => 'fourth cousin',
  232: 	'5,6' => 'fourth cousin once-removed',
  233: 	'5,7' => 'fourth cousin twice-removed',
  234: 	'5,8' => 'fourth cousin three-times-removed',
  235: 	'5,9' => 'fourth cousin four-times-removed',
  236: 	'5,10' => 'fourth cousin five-times-removed',
  237: 	'6,0' => 'great-great-great-great-grandmother',
  238: 	'6,1' => 'great-great-great-great-aunt',
  239: 	'6,2' => 'first cousin four-times-removed',
  240: 	'6,3' => 'second cousin three-times-removed',
  241: 	'6,4' => 'third cousin twice-removed',
  242: 	'6,5' => 'fourth cousin once-removed',
  243: 	'6,6' => 'fifth cousin',
  244: 	'6,7' => 'fifth cousin once-removed',
  245: 	'6,8' => 'fifth cousin twice-removed',
  246: 	'6,9' => 'fifth cousin three-times-removed',
  247: 	'6,10' => 'fifth cousin four-times-removed',
  248: 	'7,0' => 'great-great-great-great-great-grandmother',
  249: 	'7,1' => 'great-great-great-great-great-aunt',
  250: 	'7,2' => 'first cousin five-times-removed',
  251: 	'7,3' => 'second cousin four-times-removed',
  252: 	'7,4' => 'third cousin three-times-removed',
  253: 	'7,5' => 'fourth cousin twice-removed',
  254: 	'7,6' => 'fifth cousin once-removed',
  255: 	'7,7' => 'sixth cousin',
  256: 	'7,8' => 'sixth cousin once-removed',
  257: 	'7,9' => 'sixth cousin twice-removed',
  258: 	'7,10' => 'sixth cousin three-times-removed',
  259: 	'8,0' => 'great-great-great-great-great-great-grandmother',
  260: 	'8,1' => 'great-great-great-great-great-great-aunt',
  261: 	'8,2' => 'first cousin six-times-removed',
  262: 	'8,3' => 'second cousin five-times-removed',
  263: 	'8,4' => 'third cousin four-times-removed',
  264: 	'8,5' => 'fourth cousin three-times-removed',
  265: 	'8,6' => 'fifth cousin twice-removed',
  266: 	'8,7' => 'sixth cousin once-removed',
  267: 	'8,8' => 'seventh cousin',
  268: 	'8,9' => 'seventh cousin once-removed',
  269: 	'8,10' => 'seventh cousin twice-removed',
  270: 	'9,0' => 'great-great-great-great-great-great-great-grandmother',
  271: 	'9,1' => 'great-great-great-great-great-great-great-aunt',
  272: 	'9,2' => 'first cousin seven-times-removed',
  273: 	'9,3' => 'second cousin six-times-removed',
  274: 	'9,4' => 'third cousin five-times-removed',
  275: 	'9,5' => 'fourth cousin four-times-removed',
  276: 	'9,6' => 'fifth cousin three-times-removed',
  277: 	'9,7' => 'sixth cousin twice-removed',
  278: 	'9,8' => 'seventh cousin once-removed',
  279: 	'9,9' => 'eighth cousin',
  280: 	'9,10' => 'eighth cousin once-removed',
  281: 	'10,0' => 'great-great-great-great-great-great-great-great-grandmother',
  282: 	'10,1' => 'great-great-great-great-great-great-great-great-aunt',
  283: 	'10,2' => 'first cousin eight-times-removed',
  284: 	'10,3' => 'second cousin seven-times-removed',
  285: 	'10,4' => 'third cousin six-times-removed',
  286: 	'10,5' => 'fourth cousin five-times-removed',
  287: 	'10,6' => 'fifth cousin four-times-removed',
  288: 	'10,7' => 'sixth cousin three-times-removed',
  289: 	'10,8' => 'seventh cousin twice-removed',
  290: 	'10,9' => 'eighth cousin once-removed',
  291: 	'10,10' => 'ninth cousin',
  292: 	'11,1' => 'eigth great-aunt',
  293: 	'12,1' => 'ninth great-aunt',
  294: 	'13,1' => 'tenth great-aunt',
  295: 	'16,1' => 'thirteenth great-aunt',
  296: 	'17,1' => 'fourteenth great-aunt',
  297: );
  298: 
  299: # ---------------------------------------------------------------------------
  300: # French relationship tables
  301: # ---------------------------------------------------------------------------
  302: 
  303: Readonly::Hash my %FR_MALE_RELATIONSHIPS => (
  304: 	'0,0' => 'soi-meme',
  305: 	'0,1' => 'fils',
  306: 	'0,2' => 'petit-fils',
  307: 	'0,3' => 'arriere-petit-fils',
  308: 	'0,4' => 'arriere-arriere-petit-fils',
  309: 	'0,5' => 'arriere-arriere-arriere-petit-fils',
  310: 	'0,6' => 'arriere-arriere-arriere-arriere-petit-fils',
  311: 	'0,7' => 'arriere-arriere-arriere-arriere-arriere-petit-fils',
  312: 	'0,8' => 'arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
  313: 	'0,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
  314: 	'0,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-petit-fils',
  315: 	'1,0' => 'pere',
  316: 	'1,1' => "fr\N{U+00E8}re",
  317: 	'1,2' => 'neveu',
  318: 	'1,3' => 'grand-neveu',
  319: 	'1,4' => 'arriere-grand-neveu',
  320: 	'1,5' => 'arriere-arriere-grand-neveu',
  321: 	'1,6' => 'arriere-arriere-arriere-grand-neveu',
  322: 	'1,7' => 'arriere-arriere-arriere-arriere-grand-neveu',
  323: 	'1,8' => 'arriere-arriere-arriere-arriere-arriere-grand-neveu',
  324: 	'1,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-neveu',
  325: 	'1,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-neveu',
  326: 	'2,0' => 'grand-pere',
  327: 	'2,1' => 'oncle',
  328: 	'2,2' => 'cousin germain',
  329: 	'2,3' => "cousin germain \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
  330: 	'2,4' => 'cousin germain deux fois eloigne',
  331: 	'2,5' => 'cousin germain trois fois eloigne',
  332: 	'2,6' => 'cousin germain quatre fois eloigne',
  333: 	'2,7' => 'cousin germain cinq fois eloigne',
  334: 	'2,8' => 'cousin germain six fois eloigne',
  335: 	'2,9' => 'cousin germain sept fois eloigne',
  336: 	'2,10' => 'cousin germain huit fois eloigne',
  337: 	'3,0' => 'arriere-grand-pere',
  338: 	'3,1' => 'grand-oncle',
  339: 	'3,2' => 'cousin germain une fois eloigne',
  340: 	'3,2' => "cousin germain \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
  341: 	'3,3' => 'cousin issu de germain',
  342: 	'3,4' => 'cousin issu de germain une fois eloigne',
  343: 	'3,5' => "cousin issu de germains \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
  344: 	'3,6' => 'cousin issu de germain trois fois eloigne',
  345: 	'3,7' => 'cousin issu de germain quatre fois eloigne',
  346: 	'3,8' => 'cousin issu de germain cinq fois eloigne',
  347: 	'3,9' => 'cousin issu de germain six fois eloigne',
  348: 	'3,10' => 'cousin issu de germain sept fois eloigne',
  349: 	'4,0' => 'arriere-arriere-grand-pere',
  350: 	'4,1' => 'arriere-grand-oncle',
  351: 	'4,2' => 'cousin germain deux fois eloigne',
  352: 	'4,3' => 'cousin issu de germain une fois eloigne',
  353: 	'4,4' => 'cousin au quatrieme degre',
  354: 	'4,5' => 'cousin au quatrieme degre une fois eloigne',
  355: 	'4,6' => 'cousin au quatrieme degre deux fois eloigne',
  356: 	'4,7' => "petit-cousin \N{U+00E9}loign\N{U+00E9} au 3e degr\N{U+00E9}",
  357: 	'4,8' => 'cousin au quatrieme degre quatre fois eloigne',
  358: 	'4,9' => 'cousin au quatrieme degre cinq fois eloigne',
  359: 	'4,10' => 'cousin au quatrieme degre six fois eloigne',
  360: 	'5,0' => 'arriere-arriere-arriere-grand-pere',
  361: 	'5,1' => 'arriere-arriere-grand-oncle',
  362: 	'5,2' => 'cousin germain trois fois eloigne',
  363: 	'5,3' => "cousin issu de germains \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
  364: 	'5,4' => 'cousin au quatrieme degre une fois eloigne',
  365: 	'5,5' => 'cousin au cinquieme degre',
  366: 	'5,6' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
  367: 	'5,7' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
  368: 	'5,8' => 'cousin au cinquieme degre trois fois eloigne',
  369: 	'5,9' => 'cousin au cinquieme degre quatre fois eloigne',
  370: 	'5,10' => 'cousin au cinquieme degre cinq fois eloigne',
  371: 	'6,0' => 'arriere-arriere-arriere-arriere-grand-pere',
  372: 	'6,1' => 'arriere-arriere-arriere-grand-oncle',
  373: 	'6,2' => 'cousin germain quatre fois eloigne',
  374: 	'6,3' => 'cousin issu de germain trois fois eloigne',
  375: 	'6,4' => 'cousin au quatrieme degre deux fois eloigne',
  376: 	'6,5' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 1er degr\N{U+00E9}",
  377: 	'6,6' => "arri\N{U+00E8}re-arri\N{U+00E8}re-petit-cousin",
  378: 	'6,7' => 'cousin au sixieme degre une fois eloigne',
  379: 	'6,8' => 'cousin au sixieme degre deux fois eloigne',
  380: 	'6,9' => 'cousin au sixieme degre trois fois eloigne',
  381: 	'6,10' => 'cousin au sixieme degre quatre fois eloigne',
  382: 	'7,0' => 'arriere-arriere-arriere-arriere-arriere-grand-pere',
  383: 	'7,1' => 'arriere-arriere-arriere-arriere-grand-oncle',
  384: 	'7,2' => 'cousin germain cinq fois eloigne',
  385: 	'7,3' => 'cousin issu de germain quatre fois eloigne',
  386: 	'7,4' => "petit-cousin \N{U+00E9}loign\N{U+00E9} au 3e degr\N{U+00E9}",
  387: 	'7,5' => "arri\N{U+00E8}re-petit-cousin \N{U+00E9}loign\N{U+00E9} au 2e degr\N{U+00E9}",
  388: 	'7,6' => 'cousin au sixieme degre une fois eloigne',
  389: 	'7,7' => "sixi\N{U+00E8}me cousin",
  390: 	'7,8' => "sixi\N{U+00E8}me cousin uns fois eloinge",
  391: 	'7,9' => 'cousin au septieme degre deux fois eloigne',
  392: 	'7,10' => 'cousin au septieme degre trois fois eloigne',
  393: 	'8,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
  394: 	'8,1' => 'arriere-arriere-arriere-arriere-arriere-grand-oncle',
  395: 	'8,2' => 'cousin germain six fois eloigne',
  396: 	'8,3' => 'cousin issu de germain cinq fois eloigne',
  397: 	'8,4' => 'cousin au quatrieme degre quatre fois eloigne',
  398: 	'8,5' => 'cousin au cinquieme degre trois fois eloigne',
  399: 	'8,6' => 'cousin au sixieme degre deux fois eloigne',
  400: 	'8,7' => "sixi\N{U+00E8}me cousin uns fois eloinge",
  401: 	'8,8' => 'cousin au huitieme degre',
  402: 	'8,9' => 'cousin au huitieme degre une fois eloigne',
  403: 	'8,10' => 'cousin au huitieme degre deux fois eloigne',
  404: 	'9,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
  405: 	'9,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-oncle',
  406: 	'9,2' => 'cousin germain sept fois eloigne',
  407: 	'9,3' => 'cousin issu de germain six fois eloigne',
  408: 	'9,4' => 'cousin au quatrieme degre cinq fois eloigne',
  409: 	'9,5' => 'cousin au cinquieme degre quatre fois eloigne',
  410: 	'9,6' => 'cousin au sixieme degre trois fois eloigne',
  411: 	'9,7' => 'cousin au septieme degre deux fois eloigne',
  412: 	'9,8' => 'cousin au huitieme degre une fois eloigne',
  413: 	'9,9' => 'cousin au neuvieme degre',
  414: 	'9,10' => 'cousin au neuvieme degre une fois eloigne',
  415: 	'10,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-pere',
  416: 	'10,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-oncle',
  417: 	'10,2' => 'cousin germain huit fois eloigne',
  418: 	'10,3' => 'cousin issu de germain sept fois eloigne',
  419: 	'10,4' => 'cousin au quatrieme degre six fois eloigne',
  420: 	'10,5' => 'cousin au cinquieme degre cinq fois eloigne',
  421: 	'10,6' => 'cousin au sixieme degre quatre fois eloigne',
  422: 	'10,7' => 'cousin au septieme degre trois fois eloigne',
  423: 	'10,8' => 'cousin au huitieme degre deux fois eloigne',
  424: 	'10,9' => 'cousin au neuvieme degre une fois eloigne',
  425: 	'10,10' => 'cousin au dixieme degre',
  426: 	'11,1' => "huit\N{U+0153}me grand-oncle",
  427: 	'12,1' => "neuvi\N{U+0153}me grand-oncle",
  428: 	'13,1' => "dixi\N{U+0153}me grand-oncle",
  429: );
  430: 
  431: Readonly::Hash my %FR_FEMALE_RELATIONSHIPS => (
  432: 	'0,0' => 'soi-meme',
  433: 	'0,1' => 'fille',
  434: 	'0,2' => 'petite-fille',
  435: 	'0,3' => 'arriere-petite-fille',
  436: 	'0,4' => 'arriere-arriere-petite-fille',
  437: 	'0,5' => 'arriere-arriere-arriere-petite-fille',
  438: 	'0,6' => 'arriere-arriere-arriere-arriere-petite-fille',
  439: 	'0,7' => 'arriere-arriere-arriere-arriere-arriere-petite-fille',
  440: 	'0,8' => 'arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
  441: 	'0,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
  442: 	'0,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-petite-fille',
  443: 	'1,0' => 'mere',
  444: 	'1,1' => "s\N{U+0153}ur",
  445: 	'1,2' => "ni\N{U+00E8}ce",
  446: 	'1,3' => 'grand-niece',
  447: 	'1,4' => 'arriere-grand-niece',
  448: 	'1,5' => 'arriere-arriere-grand-niece',
  449: 	'1,6' => 'arriere-arriere-arriere-grand-niece',
  450: 	'1,7' => 'arriere-arriere-arriere-arriere-grand-niece',
  451: 	'1,8' => 'arriere-arriere-arriere-arriere-arriere-grand-niece',
  452: 	'1,9' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-niece',
  453: 	'1,10' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-niece',
  454: 	'2,0' => 'grand-mere',
  455: 	'2,1' => 'tante',
  456: 	'2,2' => 'cousine germaine',
  457: 	'2,3' => "cousine germaine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
  458: 	'2,4' => 'cousine germaine deux fois eloignee',
  459: 	'2,5' => 'cousine germaine trois fois eloignee',
  460: 	'2,6' => 'cousine germaine quatre fois eloignee',
  461: 	'2,7' => 'cousine germaine cinq fois eloignee',
  462: 	'2,8' => 'cousine germaine six fois eloignee',
  463: 	'2,9' => 'cousine germaine sept fois eloignee',
  464: 	'2,10' => 'cousine germaine huit fois eloignee',
  465: 	'3,0' => 'arriere-grand-mere',
  466: 	'3,1' => 'grand-tante',
  467: 	'3,2' => "cousine germaine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
  468: 	'3,3' => 'cousine issue de germaine',
  469: 	'3,4' => 'cousine issue de germaine une fois eloignee',
  470: 	'3,5' => "cousine issue de germains \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
  471: 	'3,6' => 'cousine issue de germaine trois fois eloignee',
  472: 	'3,7' => 'cousine issue de germaine quatre fois eloignee',
  473: 	'3,8' => 'cousine issue de germaine cinq fois eloignee',
  474: 	'3,9' => 'cousine issue de germaine six fois eloignee',
  475: 	'3,10' => 'cousine issue de germaine sept fois eloignee',
  476: 	'4,0' => 'arriere-arriere-grand-mere',
  477: 	'4,1' => 'arriere-grand-tante',
  478: 	'4,2' => 'cousine germaine deux fois eloignee',
  479: 	'4,3' => 'cousine issue de germaine une fois eloignee',
  480: 	'4,4' => 'cousine au quatrieme degre',
  481: 	'4,5' => 'cousine au quatrieme degre une fois eloignee',
  482: 	'4,6' => 'cousine au quatrieme degre deux fois eloignee',
  483: 	'4,7' => "petite-cousine \N{U+00E9}loign\N{U+00E9}e au 3e degr\N{U+00E9}",
  484: 	'4,8' => 'cousine au quatrieme degre quatre fois eloignee',
  485: 	'4,9' => 'cousine au quatrieme degre cinq fois eloignee',
  486: 	'4,10' => 'cousine au quatrieme degre six fois eloignee',
  487: 	'5,0' => 'arriere-arriere-arriere-grand-mere',
  488: 	'5,1' => 'arriere-arriere-grand-tante',
  489: 	'5,2' => 'cousine germaine trois fois eloignee',
  490: 	'5,3' => "cousine issue de germains \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
  491: 	'5,4' => 'cousine au quatrieme degre une fois eloignee',
  492: 	'5,5' => 'cousine au cinquieme degre',
  493: 	'5,6' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 1er degr\N{U+00E9}",
  494: 	'5,7' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
  495: 	'5,8' => 'cousine au cinquieme degre trois fois eloignee',
  496: 	'5,9' => 'cousine au cinquieme degre quatre fois eloignee',
  497: 	'5,10' => 'cousine au cinquieme degre cinq fois eloignee',
  498: 	'6,0' => 'arriere-arriere-arriere-arriere-grand-mere',
  499: 	'6,1' => 'arriere-arriere-arriere-grand-tante',
  500: 	'6,2' => 'cousine germaine quatre fois eloignee',
  501: 	'6,3' => 'cousine issue de germaine trois fois eloignee',
  502: 	'6,4' => 'cousine au quatrieme degre deux fois eloignee',
  503: 	'6,6' => "arri\N{U+00E8}re-arri\N{U+00E8}re-petite-cousine",
  504: 	'6,6' => 'cousine au sixieme degre',
  505: 	'6,7' => 'cousine au sixieme degre une fois eloignee',
  506: 	'6,8' => 'cousine au sixieme degre deux fois eloignee',
  507: 	'6,9' => 'cousine au sixieme degre trois fois eloignee',
  508: 	'6,10' => 'cousine au sixieme degre quatre fois eloignee',
  509: 	'7,0' => 'arriere-arriere-arriere-arriere-arriere-grand-mere',
  510: 	'7,1' => 'arriere-arriere-arriere-arriere-grand-tante',
  511: 	'7,2' => 'cousine germaine cinq fois eloignee',
  512: 	'7,3' => 'cousine issue de germaine quatre fois eloignee',
  513: 	'7,4' => "petite-cousine \N{U+00E9}loign\N{U+00E9}e au 3e degr\N{U+00E9}",
  514: 	'7,5' => "arri\N{U+00E8}re-petite-cousine \N{U+00E9}loign\N{U+00E9}e au 2e degr\N{U+00E9}",
  515: 	'7,6' => 'cousine au sixieme degre une fois eloignee',
  516: 	'7,7' => "sixi\N{U+00E8}me cousin",
  517: 	'7,8' => "sixi\N{U+00E8}me cousin once-removed",
  518: 	'7,9' => 'cousine au septieme degre deux fois eloignee',
  519: 	'7,10' => 'cousine au septieme degre trois fois eloignee',
  520: 	'8,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
  521: 	'8,1' => 'arriere-arriere-arriere-arriere-arriere-grand-tante',
  522: 	'8,2' => 'cousine germaine six fois eloignee',
  523: 	'8,3' => 'cousine issue de germaine cinq fois eloignee',
  524: 	'8,4' => 'cousine au quatrieme degre quatre fois eloignee',
  525: 	'8,5' => 'cousine au cinquieme degre trois fois eloignee',
  526: 	'8,6' => 'cousine au sixieme degre deux fois eloignee',
  527: 	'8,7' => "sixi\N{U+00E8}me cousin once-removed",
  528: 	'8,8' => 'cousine au huitieme degre',
  529: 	'8,9' => 'cousine au huitieme degre une fois eloignee',
  530: 	'8,10' => 'cousine au huitieme degre deux fois eloignee',
  531: 	'9,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
  532: 	'9,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-grand-tante',
  533: 	'9,2' => 'cousine germaine sept fois eloignee',
  534: 	'9,3' => 'cousine issue de germaine six fois eloignee',
  535: 	'9,4' => 'cousine au quatrieme degre cinq fois eloignee',
  536: 	'9,5' => 'cousine au cinquieme degre quatre fois eloignee',
  537: 	'9,6' => 'cousine au sixieme degre trois fois eloignee',
  538: 	'9,7' => 'cousine au septieme degre deux fois eloignee',
  539: 	'9,8' => 'cousine au huitieme degre une fois eloignee',
  540: 	'9,9' => 'cousine au neuvieme degre',
  541: 	'9,10' => 'cousine au neuvieme degre une fois eloignee',
  542: 	'10,0' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-mere',
  543: 	'10,1' => 'arriere-arriere-arriere-arriere-arriere-arriere-arriere-grand-tante',
  544: 	'10,2' => 'cousine germaine huit fois eloignee',
  545: 	'10,3' => 'cousine issue de germaine sept fois eloignee',
  546: 	'10,4' => 'cousine au quatrieme degre six fois eloignee',
  547: 	'10,5' => 'cousine au cinquieme degre cinq fois eloignee',
  548: 	'10,6' => 'cousine au sixieme degre quatre fois eloignee',
  549: 	'10,7' => 'cousine au septieme degre trois fois eloignee',
  550: 	'10,8' => 'cousine au huitieme degre deux fois eloignee',
  551: 	'10,9' => 'cousine au neuvieme degre une fois eloignee',
  552: 	'10,10' => 'cousine au dixieme degre',
  553: 	'11,1' => "huit\N{U+0153}me grand-tant",
  554: 	'12,1' => "neuvi\N{U+0153}me grand-tant",
  555: 	'13,1' => "dixi\N{U+0153}me grand-tant",
  556: );
  557: 
  558: # ---------------------------------------------------------------------------
  559: # German relationship tables
  560: # ---------------------------------------------------------------------------
  561: 
  562: Readonly::Hash my %DE_MALE_RELATIONSHIPS => (
  563: 	'0,0' => 'sich selbst',
  564: 	'0,1' => 'Sohn',
  565: 	'0,2' => 'Enkel',
  566: 	'0,3' => 'Urenkel',
  567: 	'0,4' => 'Ururenkel',
  568: 	'0,5' => 'Urururenkel',
  569: 	'0,6' => 'Ururururenkel',
  570: 	'0,7' => 'Urururururenkel',
  571: 	'0,8' => 'Ururururururenkel',
  572: 	'0,9' => 'Urururururururenkel',
  573: 	'0,10' => 'Ururururururururenkel',
  574: 	'1,0' => 'Vater',
  575: 	'1,1' => 'Bruder',
  576: 	'1,2' => 'Neffe',
  577: 	'1,3' => "Gro\N{U+00DF}neffe",
  578: 	'1,4' => 'Urgrossneffe',
  579: 	'1,5' => 'Ururgrossneffe',
  580: 	'1,6' => 'Urururgrossneffe',
  581: 	'1,7' => 'Ururururgrossneffe',
  582: 	'1,8' => 'Urururururgrossneffe',
  583: 	'1,9' => 'Ururururururgrossneffe',
  584: 	'1,10' => 'Urururururururgrossneffe',
  585: 	'2,0' => "Gro\N{U+00DF}vater",
  586: 	'2,1' => 'Onkel',
  587: 	'2,2' => 'Cousin',
  588: 	'2,3' => 'Cousin einmal entfernt',
  589: 	'2,4' => 'Cousin zweimal entfernt',
  590: 	'2,5' => 'Cousin dreimal entfernt',
  591: 	'2,6' => 'Cousin viermal entfernt',
  592: 	'2,7' => 'Cousin fuenfmal entfernt',
  593: 	'2,8' => 'Cousin sechsmal entfernt',
  594: 	'2,9' => 'Cousin siebenmal entfernt',
  595: 	'2,10' => 'Cousin achtmal entfernt',
  596: 	'3,0' => 'Urgrossvater',
  597: 	'3,1' => "Gro\N{U+00DF}onkel",
  598: 	'3,2' => 'Cousin einmal entfernt',
  599: 	'3,3' => 'Cousin zweiten Grades',
  600: 	'3,4' => 'Cousin zweiten Grades einmal entfernt',
  601: 	'3,5' => 'Cousin zweiten Grades zweimal entfernt',
  602: 	'3,6' => 'Cousin zweiten Grades dreimal entfernt',
  603: 	'3,7' => 'Cousin zweiten Grades viermal entfernt',
  604: 	'3,8' => 'Cousin zweiten Grades fuenfmal entfernt',
  605: 	'3,9' => 'Cousin zweiten Grades sechsmal entfernt',
  606: 	'3,10' => 'Cousin zweiten Grades siebenmal entfernt',
  607: 	'4,0' => 'Ururgrossvater',
  608: 	'4,1' => 'Urgrossonkel',
  609: 	'4,2' => 'Cousin zweimal entfernt',
  610: 	'4,3' => 'Cousin zweiten Grades einmal entfernt',
  611: 	'4,4' => 'Cousin dritten Grades',
  612: 	'4,5' => 'Cousin dritten Grades einmal entfernt',
  613: 	'4,6' => 'Cousin dritten Grades zweimal entfernt',
  614: 	'4,7' => 'Cousin dritten Grades dreimal entfernt',
  615: 	'4,8' => 'Cousin dritten Grades viermal entfernt',
  616: 	'4,9' => 'Cousin dritten Grades fuenfmal entfernt',
  617: 	'4,10' => 'Cousin dritten Grades sechsmal entfernt',
  618: 	'5,0' => 'Urururgrossvater',
  619: 	'5,1' => 'Ururgrossonkel',
  620: 	'5,2' => 'Cousin dreimal entfernt',
  621: 	'5,3' => 'Cousin zweiten Grades zweimal entfernt',
  622: 	'5,4' => 'Cousin dritten Grades einmal entfernt',
  623: 	'5,5' => 'Cousin vierten Grades',
  624: 	'5,6' => 'Cousin vierten Grades einmal entfernt',
  625: 	'5,7' => 'Cousin vierten Grades zweimal entfernt',
  626: 	'5,8' => 'Cousin vierten Grades dreimal entfernt',
  627: 	'5,9' => 'Cousin vierten Grades viermal entfernt',
  628: 	'5,10' => 'Cousin vierten Grades fuenfmal entfernt',
  629: 	'6,0' => 'Ururururgrossvater',
  630: 	'6,1' => 'Urururgrossonkel',
  631: 	'6,2' => 'Cousin viermal entfernt',
  632: 	'6,3' => 'Cousin zweiten Grades dreimal entfernt',
  633: 	'6,4' => 'Cousin dritten Grades zweimal entfernt',
  634: 	'6,5' => 'Cousin vierten Grades einmal entfernt',
  635: 	'6,6' => 'Cousin fuenften Grades',
  636: 	'6,7' => 'Cousin fuenften Grades einmal entfernt',
  637: 	'6,8' => 'Cousin fuenften Grades zweimal entfernt',
  638: 	'6,9' => 'Cousin fuenften Grades dreimal entfernt',
  639: 	'6,10' => 'Cousin fuenften Grades viermal entfernt',
  640: 	'7,0' => 'Urururururgrossvater',
  641: 	'7,1' => 'Ururururgrossonkel',
  642: 	'7,2' => 'Cousin fuenfmal entfernt',
  643: 	'7,3' => 'Cousin zweiten Grades viermal entfernt',
  644: 	'7,4' => 'Cousin dritten Grades dreimal entfernt',
  645: 	'7,5' => 'Cousin vierten Grades zweimal entfernt',
  646: 	'7,6' => 'Cousin fuenften Grades einmal entfernt',
  647: 	'7,7' => 'Cousin sechsten Grades',
  648: 	'7,8' => 'Cousin sechsten Grades einmal entfernt',
  649: 	'7,9' => 'Cousin sechsten Grades zweimal entfernt',
  650: 	'7,10' => 'Cousin sechsten Grades dreimal entfernt',
  651: 	'8,0' => 'Ururururururgrossvater',
  652: 	'8,1' => 'Urururururgrossonkel',
  653: 	'8,2' => 'Cousin sechsmal entfernt',
  654: 	'8,3' => 'Cousin zweiten Grades fuenfmal entfernt',
  655: 	'8,4' => 'Cousin dritten Grades viermal entfernt',
  656: 	'8,5' => 'Cousin vierten Grades dreimal entfernt',
  657: 	'8,6' => 'Cousin fuenften Grades zweimal entfernt',
  658: 	'8,7' => 'Cousin sechsten Grades einmal entfernt',
  659: 	'8,8' => 'Cousin siebten Grades',
  660: 	'8,9' => 'Cousin siebten Grades einmal entfernt',
  661: 	'8,10' => 'Cousin siebten Grades zweimal entfernt',
  662: 	'9,0' => 'Urururururururgrossvater',
  663: 	'9,1' => 'Ururururururgrossonkel',
  664: 	'9,2' => 'Cousin siebenmal entfernt',
  665: 	'9,3' => 'Cousin zweiten Grades sechsmal entfernt',
  666: 	'9,4' => 'Cousin dritten Grades fuenfmal entfernt',
  667: 	'9,5' => 'Cousin vierten Grades viermal entfernt',
  668: 	'9,6' => 'Cousin fuenften Grades dreimal entfernt',
  669: 	'9,7' => 'Cousin sechsten Grades zweimal entfernt',
  670: 	'9,8' => 'Cousin siebten Grades einmal entfernt',
  671: 	'9,9' => 'Cousin achten Grades',
  672: 	'9,10' => 'Cousin achten Grades einmal entfernt',
  673: 	'10,0' => 'Ururururururururgrossvater',
  674: 	'10,1' => 'Urururururururgrossonkel',
  675: 	'10,2' => 'Cousin achtmal entfernt',
  676: 	'10,3' => 'Cousin zweiten Grades siebenmal entfernt',
  677: 	'10,4' => 'Cousin dritten Grades sechsmal entfernt',
  678: 	'10,5' => 'Cousin vierten Grades fuenfmal entfernt',
  679: 	'10,6' => 'Cousin fuenften Grades viermal entfernt',
  680: 	'10,7' => 'Cousin sechsten Grades dreimal entfernt',
  681: 	'10,8' => 'Cousin siebten Grades zweimal entfernt',
  682: 	'10,9' => 'Cousin achten Grades einmal entfernt',
  683: 	'10,10' => 'Cousin neunten Grades',
  684: 	'11,1' => 'achtens grossonkel',
  685: 	'12,1' => 'neuntens grossonkel',
  686: 	'13,1' => 'zehntens grossonkel',
  687: );
  688: 
  689: Readonly::Hash my %DE_FEMALE_RELATIONSHIPS => (
  690: 	'0,0' => 'sich selbst',
  691: 	'0,1' => 'Tochter',
  692: 	'0,2' => 'Enkelin',
  693: 	'0,3' => 'Urenkelin',
  694: 	'0,4' => 'Ururenkelin',
  695: 	'0,5' => 'Urururenkelin',
  696: 	'0,6' => 'Ururururenkelin',
  697: 	'0,7' => 'Urururururenkelin',
  698: 	'0,8' => 'Ururururururenkelin',
  699: 	'0,9' => 'Urururururururenkelin',
  700: 	'0,10' => 'Ururururururururenkelin',
  701: 	'1,0' => 'Mutter',
  702: 	'1,1' => 'Schwester',
  703: 	'1,2' => 'Nichte',
  704: 	'1,3' => "Gro\N{U+00DF}nichte",
  705: 	'1,4' => 'Urgrossnichte',
  706: 	'1,5' => 'Ururgrossnichte',
  707: 	'1,6' => 'Urururgrossnichte',
  708: 	'1,7' => 'Ururururgrossnichte',
  709: 	'1,8' => 'Urururururgrossnichte',
  710: 	'1,9' => 'Ururururururgrossnichte',
  711: 	'1,10' => 'Urururururururgrossnichte',
  712: 	'2,0' => "Gro\N{U+00DF}mutter",
  713: 	'2,1' => 'Tante',
  714: 	'2,2' => 'Cousine',
  715: 	'2,3' => 'Cousine einmal entfernt',
  716: 	'2,4' => 'Cousine zweimal entfernt',
  717: 	'2,5' => 'Cousine dreimal entfernt',
  718: 	'2,6' => 'Cousine viermal entfernt',
  719: 	'2,7' => 'Cousine fuenfmal entfernt',
  720: 	'2,8' => 'Cousine sechsmal entfernt',
  721: 	'2,9' => 'Cousine siebenmal entfernt',
  722: 	'2,10' => 'Cousine achtmal entfernt',
  723: 	'3,0' => 'Urgrossmutter',
  724: 	'3,1' => "Gro\N{U+00DF}tante",
  725: 	'3,2' => 'Cousine einmal entfernt',
  726: 	'3,3' => 'Cousine zweiten Grades',
  727: 	'3,4' => 'Cousine zweiten Grades einmal entfernt',
  728: 	'3,5' => 'Cousine zweiten Grades zweimal entfernt',
  729: 	'3,6' => 'Cousine zweiten Grades dreimal entfernt',
  730: 	'3,7' => 'Cousine zweiten Grades viermal entfernt',
  731: 	'3,8' => 'Cousine zweiten Grades fuenfmal entfernt',
  732: 	'3,9' => 'Cousine zweiten Grades sechsmal entfernt',
  733: 	'3,10' => 'Cousine zweiten Grades siebenmal entfernt',
  734: 	'4,0' => 'Ururgrossmutter',
  735: 	'4,1' => 'Urgrosstante',
  736: 	'4,2' => 'Cousine zweimal entfernt',
  737: 	'4,3' => 'Cousine zweiten Grades einmal entfernt',
  738: 	'4,4' => 'Cousine dritten Grades',
  739: 	'4,5' => 'Cousine dritten Grades einmal entfernt',
  740: 	'4,6' => 'Cousine dritten Grades zweimal entfernt',
  741: 	'4,7' => 'Cousine dritten Grades dreimal entfernt',
  742: 	'4,8' => 'Cousine dritten Grades viermal entfernt',
  743: 	'4,9' => 'Cousine dritten Grades fuenfmal entfernt',
  744: 	'4,10' => 'Cousine dritten Grades sechsmal entfernt',
  745: 	'5,0' => 'Urururgrossmutter',
  746: 	'5,1' => 'Ururgrosstante',
  747: 	'5,2' => 'Cousine dreimal entfernt',
  748: 	'5,3' => 'Cousine zweiten Grades zweimal entfernt',
  749: 	'5,4' => 'Cousine dritten Grades einmal entfernt',
  750: 	'5,5' => 'Cousine vierten Grades',
  751: 	'5,6' => 'Cousine vierten Grades einmal entfernt',
  752: 	'5,7' => 'Cousine vierten Grades zweimal entfernt',
  753: 	'5,8' => 'Cousine vierten Grades dreimal entfernt',
  754: 	'5,9' => 'Cousine vierten Grades viermal entfernt',
  755: 	'5,10' => 'Cousine vierten Grades fuenfmal entfernt',
  756: 	'6,0' => 'Ururururgrossmutter',
  757: 	'6,1' => 'Urururgrosstante',
  758: 	'6,2' => 'Cousine viermal entfernt',
  759: 	'6,3' => 'Cousine zweiten Grades dreimal entfernt',
  760: 	'6,4' => 'Cousine dritten Grades zweimal entfernt',
  761: 	'6,5' => 'Cousine vierten Grades einmal entfernt',
  762: 	'6,6' => 'Cousine fuenften Grades',
  763: 	'6,7' => 'Cousine fuenften Grades einmal entfernt',
  764: 	'6,8' => 'Cousine fuenften Grades zweimal entfernt',
  765: 	'6,9' => 'Cousine fuenften Grades dreimal entfernt',
  766: 	'6,10' => 'Cousine fuenften Grades viermal entfernt',
  767: 	'7,0' => 'Urururururgrossmutter',
  768: 	'7,1' => 'Ururururgrosstante',
  769: 	'7,2' => 'Cousine fuenfmal entfernt',
  770: 	'7,3' => 'Cousine zweiten Grades viermal entfernt',
  771: 	'7,4' => 'Cousine dritten Grades dreimal entfernt',
  772: 	'7,5' => 'Cousine vierten Grades zweimal entfernt',
  773: 	'7,6' => 'Cousine fuenften Grades einmal entfernt',
  774: 	'7,7' => 'Cousine sechsten Grades',
  775: 	'7,8' => 'Cousine sechsten Grades einmal entfernt',
  776: 	'7,9' => 'Cousine sechsten Grades zweimal entfernt',
  777: 	'7,10' => 'Cousine sechsten Grades dreimal entfernt',
  778: 	'8,0' => 'Ururururururgrossmutter',
  779: 	'8,1' => 'Urururururgrosstante',
  780: 	'8,2' => 'Cousine sechsmal entfernt',
  781: 	'8,3' => 'Cousine zweiten Grades fuenfmal entfernt',
  782: 	'8,4' => 'Cousine dritten Grades viermal entfernt',
  783: 	'8,5' => 'Cousine vierten Grades dreimal entfernt',
  784: 	'8,6' => 'Cousine fuenften Grades zweimal entfernt',
  785: 	'8,7' => 'Cousine sechsten Grades einmal entfernt',
  786: 	'8,8' => 'Cousine siebten Grades',
  787: 	'8,9' => 'Cousine siebten Grades einmal entfernt',
  788: 	'8,10' => 'Cousine siebten Grades zweimal entfernt',
  789: 	'9,0' => 'Urururururururgrossmutter',
  790: 	'9,1' => 'Ururururururgrosstante',
  791: 	'9,2' => 'Cousine siebenmal entfernt',
  792: 	'9,3' => 'Cousine zweiten Grades sechsmal entfernt',
  793: 	'9,4' => 'Cousine dritten Grades fuenfmal entfernt',
  794: 	'9,5' => 'Cousine vierten Grades viermal entfernt',
  795: 	'9,6' => 'Cousine fuenften Grades dreimal entfernt',
  796: 	'9,7' => 'Cousine sechsten Grades zweimal entfernt',
  797: 	'9,8' => 'Cousine siebten Grades einmal entfernt',
  798: 	'9,9' => 'Cousine achten Grades',
  799: 	'9,10' => 'Cousine achten Grades einmal entfernt',
  800: 	'10,0' => 'Ururururururururgrossmutter',
  801: 	'10,1' => 'Urururururururgrosstante',
  802: 	'10,2' => 'Cousine achtmal entfernt',
  803: 	'10,3' => 'Cousine zweiten Grades siebenmal entfernt',
  804: 	'10,4' => 'Cousine dritten Grades sechsmal entfernt',
  805: 	'10,5' => 'Cousine vierten Grades fuenfmal entfernt',
  806: 	'10,6' => 'Cousine fuenften Grades viermal entfernt',
  807: 	'10,7' => 'Cousine sechsten Grades dreimal entfernt',
  808: 	'10,8' => 'Cousine siebten Grades zweimal entfernt',
  809: 	'10,9' => 'Cousine achten Grades einmal entfernt',
  810: 	'10,10' => 'Cousine neunten Grades',
  811: 	'11,1' => 'achtens grosstante',
  812: 	'12,1' => 'neuntens grosstante',
  813: 	'13,1' => 'zehntens grosstante',
  814: );
  815: 
  816: # ---------------------------------------------------------------------------
  817: # Swiss German (de-CH) relationship tables
  818: # Uses 'ss' instead of Eszett (\N{U+00DF}); Switzerland abolished ß in 1934
  819: # ---------------------------------------------------------------------------
  820: 
  821: Readonly::Hash my %DE_CH_MALE_RELATIONSHIPS => (
  822: 	'0,0' => 'sich selbst',
  823: 	'0,1' => 'Sohn',
  824: 	'0,2' => 'Enkel',
  825: 	'0,3' => 'Urenkel',
  826: 	'0,4' => 'Ururenkel',
  827: 	'0,5' => 'Urururenkel',
  828: 	'0,6' => 'Ururururenkel',
  829: 	'0,7' => 'Urururururenkel',
  830: 	'0,8' => 'Ururururururenkel',
  831: 	'0,9' => 'Urururururururenkel',
  832: 	'0,10' => 'Ururururururururenkel',
  833: 	'1,0' => 'Vater',
  834: 	'1,1' => 'Bruder',
  835: 	'1,2' => 'Neffe',
  836: 	'1,3' => 'Grossneffe',
  837: 	'1,4' => 'Urgrossneffe',
  838: 	'1,5' => 'Ururgrossneffe',
  839: 	'1,6' => 'Urururgrossneffe',
  840: 	'1,7' => 'Ururururgrossneffe',
  841: 	'1,8' => 'Urururururgrossneffe',
  842: 	'1,9' => 'Ururururururgrossneffe',
  843: 	'1,10' => 'Urururururururgrossneffe',
  844: 	'2,0' => 'Grossvater',
  845: 	'2,1' => 'Onkel',
  846: 	'2,2' => 'Cousin',
  847: 	'2,3' => 'Cousin einmal entfernt',
  848: 	'2,4' => 'Cousin zweimal entfernt',
  849: 	'2,5' => 'Cousin dreimal entfernt',
  850: 	'2,6' => 'Cousin viermal entfernt',
  851: 	'2,7' => 'Cousin fuenfmal entfernt',
  852: 	'2,8' => 'Cousin sechsmal entfernt',
  853: 	'2,9' => 'Cousin siebenmal entfernt',
  854: 	'2,10' => 'Cousin achtmal entfernt',
  855: 	'3,0' => 'Urgrossvater',
  856: 	'3,1' => 'Grossonkel',
  857: 	'3,2' => 'Cousin einmal entfernt',
  858: 	'3,3' => 'Cousin zweiten Grades',
  859: 	'3,4' => 'Cousin zweiten Grades einmal entfernt',
  860: 	'3,5' => 'Cousin zweiten Grades zweimal entfernt',
  861: 	'3,6' => 'Cousin zweiten Grades dreimal entfernt',
  862: 	'3,7' => 'Cousin zweiten Grades viermal entfernt',
  863: 	'3,8' => 'Cousin zweiten Grades fuenfmal entfernt',
  864: 	'3,9' => 'Cousin zweiten Grades sechsmal entfernt',
  865: 	'3,10' => 'Cousin zweiten Grades siebenmal entfernt',
  866: 	'4,0' => 'Ururgrossvater',
  867: 	'4,1' => 'Urgrossonkel',
  868: 	'4,2' => 'Cousin zweimal entfernt',
  869: 	'4,3' => 'Cousin zweiten Grades einmal entfernt',
  870: 	'4,4' => 'Cousin dritten Grades',
  871: 	'4,5' => 'Cousin dritten Grades einmal entfernt',
  872: 	'4,6' => 'Cousin dritten Grades zweimal entfernt',
  873: 	'4,7' => 'Cousin dritten Grades dreimal entfernt',
  874: 	'4,8' => 'Cousin dritten Grades viermal entfernt',
  875: 	'4,9' => 'Cousin dritten Grades fuenfmal entfernt',
  876: 	'4,10' => 'Cousin dritten Grades sechsmal entfernt',
  877: 	'5,0' => 'Urururgrossvater',
  878: 	'5,1' => 'Ururgrossonkel',
  879: 	'5,2' => 'Cousin dreimal entfernt',
  880: 	'5,3' => 'Cousin zweiten Grades zweimal entfernt',
  881: 	'5,4' => 'Cousin dritten Grades einmal entfernt',
  882: 	'5,5' => 'Cousin vierten Grades',
  883: 	'5,6' => 'Cousin vierten Grades einmal entfernt',
  884: 	'5,7' => 'Cousin vierten Grades zweimal entfernt',
  885: 	'5,8' => 'Cousin vierten Grades dreimal entfernt',
  886: 	'5,9' => 'Cousin vierten Grades viermal entfernt',
  887: 	'5,10' => 'Cousin vierten Grades fuenfmal entfernt',
  888: 	'6,0' => 'Ururururgrossvater',
  889: 	'6,1' => 'Urururgrossonkel',
  890: 	'6,2' => 'Cousin viermal entfernt',
  891: 	'6,3' => 'Cousin zweiten Grades dreimal entfernt',
  892: 	'6,4' => 'Cousin dritten Grades zweimal entfernt',
  893: 	'6,5' => 'Cousin vierten Grades einmal entfernt',
  894: 	'6,6' => 'Cousin fuenften Grades',
  895: 	'6,7' => 'Cousin fuenften Grades einmal entfernt',
  896: 	'6,8' => 'Cousin fuenften Grades zweimal entfernt',
  897: 	'6,9' => 'Cousin fuenften Grades dreimal entfernt',
  898: 	'6,10' => 'Cousin fuenften Grades viermal entfernt',
  899: 	'7,0' => 'Urururururgrossvater',
  900: 	'7,1' => 'Ururururgrossonkel',
  901: 	'7,2' => 'Cousin fuenfmal entfernt',
  902: 	'7,3' => 'Cousin zweiten Grades viermal entfernt',
  903: 	'7,4' => 'Cousin dritten Grades dreimal entfernt',
  904: 	'7,5' => 'Cousin vierten Grades zweimal entfernt',
  905: 	'7,6' => 'Cousin fuenften Grades einmal entfernt',
  906: 	'7,7' => 'Cousin sechsten Grades',
  907: 	'7,8' => 'Cousin sechsten Grades einmal entfernt',
  908: 	'7,9' => 'Cousin sechsten Grades zweimal entfernt',
  909: 	'7,10' => 'Cousin sechsten Grades dreimal entfernt',
  910: 	'8,0' => 'Ururururururgrossvater',
  911: 	'8,1' => 'Urururururgrossonkel',
  912: 	'8,2' => 'Cousin sechsmal entfernt',
  913: 	'8,3' => 'Cousin zweiten Grades fuenfmal entfernt',
  914: 	'8,4' => 'Cousin dritten Grades viermal entfernt',
  915: 	'8,5' => 'Cousin vierten Grades dreimal entfernt',
  916: 	'8,6' => 'Cousin fuenften Grades zweimal entfernt',
  917: 	'8,7' => 'Cousin sechsten Grades einmal entfernt',
  918: 	'8,8' => 'Cousin siebten Grades',
  919: 	'8,9' => 'Cousin siebten Grades einmal entfernt',
  920: 	'8,10' => 'Cousin siebten Grades zweimal entfernt',
  921: 	'9,0' => 'Urururururururgrossvater',
  922: 	'9,1' => 'Ururururururgrossonkel',
  923: 	'9,2' => 'Cousin siebenmal entfernt',
  924: 	'9,3' => 'Cousin zweiten Grades sechsmal entfernt',
  925: 	'9,4' => 'Cousin dritten Grades fuenfmal entfernt',
  926: 	'9,5' => 'Cousin vierten Grades viermal entfernt',
  927: 	'9,6' => 'Cousin fuenften Grades dreimal entfernt',
  928: 	'9,7' => 'Cousin sechsten Grades zweimal entfernt',
  929: 	'9,8' => 'Cousin siebten Grades einmal entfernt',
  930: 	'9,9' => 'Cousin achten Grades',
  931: 	'9,10' => 'Cousin achten Grades einmal entfernt',
  932: 	'10,0' => 'Ururururururururgrossvater',
  933: 	'10,1' => 'Urururururururgrossonkel',
  934: 	'10,2' => 'Cousin achtmal entfernt',
  935: 	'10,3' => 'Cousin zweiten Grades siebenmal entfernt',
  936: 	'10,4' => 'Cousin dritten Grades sechsmal entfernt',
  937: 	'10,5' => 'Cousin vierten Grades fuenfmal entfernt',
  938: 	'10,6' => 'Cousin fuenften Grades viermal entfernt',
  939: 	'10,7' => 'Cousin sechsten Grades dreimal entfernt',
  940: 	'10,8' => 'Cousin siebten Grades zweimal entfernt',
  941: 	'10,9' => 'Cousin achten Grades einmal entfernt',
  942: 	'10,10' => 'Cousin neunten Grades',
  943: 	'12,1' => 'neuntens grossonkel',
  944: 	'13,1' => 'zehntens grossonkel',
  945: );
  946: 
  947: Readonly::Hash my %DE_CH_FEMALE_RELATIONSHIPS => (
  948: 	'0,0' => 'sich selbst',
  949: 	'0,1' => 'Tochter',
  950: 	'0,2' => 'Enkelin',
  951: 	'0,3' => 'Urenkelin',
  952: 	'0,4' => 'Ururenkelin',
  953: 	'0,5' => 'Urururenkelin',
  954: 	'0,6' => 'Ururururenkelin',
  955: 	'0,7' => 'Urururururenkelin',
  956: 	'0,8' => 'Ururururururenkelin',
  957: 	'0,9' => 'Urururururururenkelin',
  958: 	'0,10' => 'Ururururururururenkelin',
  959: 	'1,0' => 'Mutter',
  960: 	'1,1' => 'Schwester',
  961: 	'1,2' => 'Nichte',
  962: 	'1,3' => 'Grossnichte',
  963: 	'1,4' => 'Urgrossnichte',
  964: 	'1,5' => 'Ururgrossnichte',
  965: 	'1,6' => 'Urururgrossnichte',
  966: 	'1,7' => 'Ururururgrossnichte',
  967: 	'1,8' => 'Urururururgrossnichte',
  968: 	'1,9' => 'Ururururururgrossnichte',
  969: 	'1,10' => 'Urururururururgrossnichte',
  970: 	'2,0' => 'Grossmutter',
  971: 	'2,1' => 'Tante',
  972: 	'2,2' => 'Cousine',
  973: 	'2,3' => 'Cousine einmal entfernt',
  974: 	'2,4' => 'Cousine zweimal entfernt',
  975: 	'2,5' => 'Cousine dreimal entfernt',
  976: 	'2,6' => 'Cousine viermal entfernt',
  977: 	'2,7' => 'Cousine fuenfmal entfernt',
  978: 	'2,8' => 'Cousine sechsmal entfernt',
  979: 	'2,9' => 'Cousine siebenmal entfernt',
  980: 	'2,10' => 'Cousine achtmal entfernt',
  981: 	'3,0' => 'Urgrossmutter',
  982: 	'3,1' => 'Grosstante',
  983: 	'3,2' => 'Cousine einmal entfernt',
  984: 	'3,3' => 'Cousine zweiten Grades',
  985: 	'3,4' => 'Cousine zweiten Grades einmal entfernt',
  986: 	'3,5' => 'Cousine zweiten Grades zweimal entfernt',
  987: 	'3,6' => 'Cousine zweiten Grades dreimal entfernt',
  988: 	'3,7' => 'Cousine zweiten Grades viermal entfernt',
  989: 	'3,8' => 'Cousine zweiten Grades fuenfmal entfernt',
  990: 	'3,9' => 'Cousine zweiten Grades sechsmal entfernt',
  991: 	'3,10' => 'Cousine zweiten Grades siebenmal entfernt',
  992: 	'4,0' => 'Ururgrossmutter',
  993: 	'4,1' => 'Urgrosstante',
  994: 	'4,2' => 'Cousine zweimal entfernt',
  995: 	'4,3' => 'Cousine zweiten Grades einmal entfernt',
  996: 	'4,4' => 'Cousine dritten Grades',
  997: 	'4,5' => 'Cousine dritten Grades einmal entfernt',
  998: 	'4,6' => 'Cousine dritten Grades zweimal entfernt',
  999: 	'4,7' => 'Cousine dritten Grades dreimal entfernt',
 1000: 	'4,8' => 'Cousine dritten Grades viermal entfernt',
 1001: 	'4,9' => 'Cousine dritten Grades fuenfmal entfernt',
 1002: 	'4,10' => 'Cousine dritten Grades sechsmal entfernt',
 1003: 	'5,0' => 'Urururgrossmutter',
 1004: 	'5,1' => 'Ururgrosstante',
 1005: 	'5,2' => 'Cousine dreimal entfernt',
 1006: 	'5,3' => 'Cousine zweiten Grades zweimal entfernt',
 1007: 	'5,4' => 'Cousine dritten Grades einmal entfernt',
 1008: 	'5,5' => 'Cousine vierten Grades',
 1009: 	'5,6' => 'Cousine vierten Grades einmal entfernt',
 1010: 	'5,7' => 'Cousine vierten Grades zweimal entfernt',
 1011: 	'5,8' => 'Cousine vierten Grades dreimal entfernt',
 1012: 	'5,9' => 'Cousine vierten Grades viermal entfernt',
 1013: 	'5,10' => 'Cousine vierten Grades fuenfmal entfernt',
 1014: 	'6,0' => 'Ururururgrossmutter',
 1015: 	'6,1' => 'Urururgrosstante',
 1016: 	'6,2' => 'Cousine viermal entfernt',
 1017: 	'6,3' => 'Cousine zweiten Grades dreimal entfernt',
 1018: 	'6,4' => 'Cousine dritten Grades zweimal entfernt',
 1019: 	'6,5' => 'Cousine vierten Grades einmal entfernt',
 1020: 	'6,6' => 'Cousine fuenften Grades',
 1021: 	'6,7' => 'Cousine fuenften Grades einmal entfernt',
 1022: 	'6,8' => 'Cousine fuenften Grades zweimal entfernt',
 1023: 	'6,9' => 'Cousine fuenften Grades dreimal entfernt',
 1024: 	'6,10' => 'Cousine fuenften Grades viermal entfernt',
 1025: 	'7,0' => 'Urururururgrossmutter',
 1026: 	'7,1' => 'Ururururgrosstante',
 1027: 	'7,2' => 'Cousine fuenfmal entfernt',
 1028: 	'7,3' => 'Cousine zweiten Grades viermal entfernt',
 1029: 	'7,4' => 'Cousine dritten Grades dreimal entfernt',
 1030: 	'7,5' => 'Cousine vierten Grades zweimal entfernt',
 1031: 	'7,6' => 'Cousine fuenften Grades einmal entfernt',
 1032: 	'7,7' => 'Cousine sechsten Grades',
 1033: 	'7,8' => 'Cousine sechsten Grades einmal entfernt',
 1034: 	'7,9' => 'Cousine sechsten Grades zweimal entfernt',
 1035: 	'7,10' => 'Cousine sechsten Grades dreimal entfernt',
 1036: 	'8,0' => 'Ururururururgrossmutter',
 1037: 	'8,1' => 'Urururururgrosstante',
 1038: 	'8,2' => 'Cousine sechsmal entfernt',
 1039: 	'8,3' => 'Cousine zweiten Grades fuenfmal entfernt',
 1040: 	'8,4' => 'Cousine dritten Grades viermal entfernt',
 1041: 	'8,5' => 'Cousine vierten Grades dreimal entfernt',
 1042: 	'8,6' => 'Cousine fuenften Grades zweimal entfernt',
 1043: 	'8,7' => 'Cousine sechsten Grades einmal entfernt',
 1044: 	'8,8' => 'Cousine siebten Grades',
 1045: 	'8,9' => 'Cousine siebten Grades einmal entfernt',
 1046: 	'8,10' => 'Cousine siebten Grades zweimal entfernt',
 1047: 	'9,0' => 'Urururururururgrossmutter',
 1048: 	'9,1' => 'Ururururururgrosstante',
 1049: 	'9,2' => 'Cousine siebenmal entfernt',
 1050: 	'9,3' => 'Cousine zweiten Grades sechsmal entfernt',
 1051: 	'9,4' => 'Cousine dritten Grades fuenfmal entfernt',
 1052: 	'9,5' => 'Cousine vierten Grades viermal entfernt',
 1053: 	'9,6' => 'Cousine fuenften Grades dreimal entfernt',
 1054: 	'9,7' => 'Cousine sechsten Grades zweimal entfernt',
 1055: 	'9,8' => 'Cousine siebten Grades einmal entfernt',
 1056: 	'9,9' => 'Cousine achten Grades',
 1057: 	'9,10' => 'Cousine achten Grades einmal entfernt',
 1058: 	'10,0' => 'Ururururururururgrossmutter',
 1059: 	'10,1' => 'Urururururururgrosstante',
 1060: 	'10,2' => 'Cousine achtmal entfernt',
 1061: 	'10,3' => 'Cousine zweiten Grades siebenmal entfernt',
 1062: 	'10,4' => 'Cousine dritten Grades sechsmal entfernt',
 1063: 	'10,5' => 'Cousine vierten Grades fuenfmal entfernt',
 1064: 	'10,6' => 'Cousine fuenften Grades viermal entfernt',
 1065: 	'10,7' => 'Cousine sechsten Grades dreimal entfernt',
 1066: 	'10,8' => 'Cousine siebten Grades zweimal entfernt',
 1067: 	'10,9' => 'Cousine achten Grades einmal entfernt',
 1068: 	'10,10' => 'Cousine neunten Grades',
 1069: 	'12,1' => 'neuntens grosstant',
 1070: 	'13,1' => 'zehntens grosstant',
 1071: );
 1072: 
 1073: # ---------------------------------------------------------------------------
 1074: # Spanish relationship tables
 1075: # ---------------------------------------------------------------------------
 1076: 
 1077: Readonly::Hash my %ES_MALE_RELATIONSHIPS => (
 1078: 	'0,0' => 'uno mismo',
 1079: 	'0,1' => 'hijo',
 1080: 	'0,2' => 'nieto',
 1081: 	'0,3' => 'bisnieto',
 1082: 	'0,4' => 'tataranieto',
 1083: 	'0,5' => 'chozno',
 1084: 	'0,6' => 'bisnieto quinto',
 1085: 	'0,7' => 'descendiente lejano',
 1086: 	'0,8' => 'descendiente lejano',
 1087: 	'0,9' => 'descendiente lejano',
 1088: 	'0,10' => 'descendiente lejano',
 1089: 	'1,0' => 'padre',
 1090: 	'1,1' => 'hermano',
 1091: 	'1,2' => 'sobrino',
 1092: 	'1,3' => 'sobrino nieto',
 1093: 	'1,4' => 'sobrino bisnieto',
 1094: 	'1,5' => 'sobrino tataranieto',
 1095: 	'1,6' => 'sobrino lejano',
 1096: 	'1,7' => 'sobrino lejano',
 1097: 	'1,8' => 'sobrino lejano',
 1098: 	'1,9' => 'sobrino lejano',
 1099: 	'1,10' => 'sobrino lejano',
 1100: 	'2,0' => 'abuelo',
 1101: 	'2,1' => 'tio',
 1102: 	'2,2' => 'primo hermano',
 1103: 	'2,3' => 'primo hermano una vez removido',
 1104: 	'2,4' => 'primo hermano dos veces removido',
 1105: 	'2,5' => 'primo hermano tres veces removido',
 1106: 	'2,6' => 'primo hermano cuatro veces removido',
 1107: 	'2,7' => 'primo hermano cinco veces removido',
 1108: 	'2,8' => 'primo hermano seis veces removido',
 1109: 	'2,9' => 'primo hermano siete veces removido',
 1110: 	'2,10' => 'primo hermano ocho veces removido',
 1111: 	'3,0' => 'bisabuelo',
 1112: 	'3,1' => 'tio abuelo',
 1113: 	'3,2' => 'primo hermano una vez removido',
 1114: 	'3,3' => 'primo segundo',
 1115: 	'3,4' => 'primo segundo una vez removido',
 1116: 	'3,5' => 'primo segundo dos veces removido',
 1117: 	'3,6' => 'primo segundo tres veces removido',
 1118: 	'3,7' => 'primo segundo cuatro veces removido',
 1119: 	'3,8' => 'primo segundo cinco veces removido',
 1120: 	'3,9' => 'primo segundo seis veces removido',
 1121: 	'3,10' => 'primo segundo siete veces removido',
 1122: 	'4,0' => 'tatarabuelo',
 1123: 	'4,1' => 'tio bisabuelo',
 1124: 	'4,2' => 'primo hermano dos veces removido',
 1125: 	'4,3' => 'primo segundo una vez removido',
 1126: 	'4,4' => 'primo tercero',
 1127: 	'4,5' => 'primo tercero una vez removido',
 1128: 	'4,6' => 'primo tercero dos veces removido',
 1129: 	'4,7' => 'primo tercero tres veces removido',
 1130: 	'4,8' => 'primo tercero cuatro veces removido',
 1131: 	'4,9' => 'primo tercero cinco veces removido',
 1132: 	'4,10' => 'primo tercero seis veces removido',
 1133: 	'5,0' => 'chozno',
 1134: 	'5,1' => 'tio tatarabuelo',
 1135: 	'5,2' => 'primo hermano tres veces removido',
 1136: 	'5,3' => 'primo segundo dos veces removido',
 1137: 	'5,4' => 'primo tercero una vez removido',
 1138: 	'5,5' => 'primo cuarto',
 1139: 	'5,6' => 'primo cuarto una vez removido',
 1140: 	'5,7' => 'primo cuarto dos veces removido',
 1141: 	'5,8' => 'primo cuarto tres veces removido',
 1142: 	'5,9' => 'primo cuarto cuatro veces removido',
 1143: 	'5,10' => 'primo cuarto cinco veces removido',
 1144: 	'6,0' => 'bisabuelo quinto',
 1145: 	'6,1' => 'tio lejano',
 1146: 	'6,2' => 'primo hermano cuatro veces removido',
 1147: 	'6,3' => 'primo segundo tres veces removido',
 1148: 	'6,4' => 'primo tercero dos veces removido',
 1149: 	'6,5' => 'primo cuarto una vez removido',
 1150: 	'6,6' => 'primo quinto',
 1151: 	'6,7' => 'primo quinto una vez removido',
 1152: 	'6,8' => 'primo quinto dos veces removido',
 1153: 	'6,9' => 'primo quinto tres veces removido',
 1154: 	'6,10' => 'primo quinto cuatro veces removido',
 1155: 	'7,0' => 'antepasado lejano',
 1156: 	'7,1' => 'tio lejano',
 1157: 	'7,2' => 'primo hermano cinco veces removido',
 1158: 	'7,3' => 'primo segundo cuatro veces removido',
 1159: 	'7,4' => 'primo tercero tres veces removido',
 1160: 	'7,5' => 'primo cuarto dos veces removido',
 1161: 	'7,6' => 'primo quinto una vez removido',
 1162: 	'7,7' => 'primo sexto',
 1163: 	'7,8' => 'primo sexto una vez removido',
 1164: 	'7,9' => 'primo sexto dos veces removido',
 1165: 	'7,10' => 'primo sexto tres veces removido',
 1166: 	'8,0' => 'antepasado lejano',
 1167: 	'8,1' => 'tio lejano',
 1168: 	'8,2' => 'primo hermano seis veces removido',
 1169: 	'8,3' => 'primo segundo cinco veces removido',
 1170: 	'8,4' => 'primo tercero cuatro veces removido',
 1171: 	'8,5' => 'primo cuarto tres veces removido',
 1172: 	'8,6' => 'primo quinto dos veces removido',
 1173: 	'8,7' => 'primo sexto una vez removido',
 1174: 	'8,8' => 'primo septimo',
 1175: 	'8,9' => 'primo septimo una vez removido',
 1176: 	'8,10' => 'primo septimo dos veces removido',
 1177: 	'9,0' => 'antepasado lejano',
 1178: 	'9,1' => 'tio lejano',
 1179: 	'9,2' => 'primo hermano siete veces removido',
 1180: 	'9,3' => 'primo segundo seis veces removido',
 1181: 	'9,4' => 'primo tercero cinco veces removido',
 1182: 	'9,5' => 'primo cuarto cuatro veces removido',
 1183: 	'9,6' => 'primo quinto tres veces removido',
 1184: 	'9,7' => 'primo sexto dos veces removido',
 1185: 	'9,8' => 'primo septimo una vez removido',
 1186: 	'9,9' => 'primo octavo',
 1187: 	'9,10' => 'primo octavo una vez removido',
 1188: 	'10,0' => 'antepasado lejano',
 1189: 	'10,1' => 'tio lejano',
 1190: 	'10,2' => 'primo hermano ocho veces removido',
 1191: 	'10,3' => 'primo segundo siete veces removido',
 1192: 	'10,4' => 'primo tercero seis veces removido',
 1193: 	'10,5' => 'primo cuarto cinco veces removido',
 1194: 	'10,6' => 'primo quinto cuatro veces removido',
 1195: 	'10,7' => 'primo sexto tres veces removido',
 1196: 	'10,8' => 'primo septimo dos veces removido',
 1197: 	'10,9' => 'primo octavo una vez removido',
 1198: 	'10,10' => 'primo noveno',
 1199: );
 1200: 
 1201: Readonly::Hash my %ES_FEMALE_RELATIONSHIPS => (
 1202: 	'0,0' => 'una misma',
 1203: 	'0,1' => 'hija',
 1204: 	'0,2' => 'nieta',
 1205: 	'0,3' => 'bisnieta',
 1206: 	'0,4' => 'tataranieta',
 1207: 	'0,5' => 'chozna',
 1208: 	'0,6' => 'bisnieta quinta',
 1209: 	'0,7' => 'descendiente lejana',
 1210: 	'0,8' => 'descendiente lejana',
 1211: 	'0,9' => 'descendiente lejana',
 1212: 	'0,10' => 'descendiente lejana',
 1213: 	'1,0' => 'madre',
 1214: 	'1,1' => 'hermana',
 1215: 	'1,2' => 'sobrina',
 1216: 	'1,3' => 'sobrina nieta',
 1217: 	'1,4' => 'sobrina bisnieta',
 1218: 	'1,5' => 'sobrina tataranieta',
 1219: 	'1,6' => 'sobrina lejana',
 1220: 	'1,7' => 'sobrina lejana',
 1221: 	'1,8' => 'sobrina lejana',
 1222: 	'1,9' => 'sobrina lejana',
 1223: 	'1,10' => 'sobrina lejana',
 1224: 	'2,0' => 'abuela',
 1225: 	'2,1' => 'tia',
 1226: 	'2,2' => 'prima hermana',
 1227: 	'2,3' => 'prima hermana una vez removida',
 1228: 	'2,4' => 'prima hermana dos veces removida',
 1229: 	'2,5' => 'prima hermana tres veces removida',
 1230: 	'2,6' => 'prima hermana cuatro veces removida',
 1231: 	'2,7' => 'prima hermana cinco veces removida',
 1232: 	'2,8' => 'prima hermana seis veces removida',
 1233: 	'2,9' => 'prima hermana siete veces removida',
 1234: 	'2,10' => 'prima hermana ocho veces removida',
 1235: 	'3,0' => 'bisabuela',
 1236: 	'3,1' => 'tia abuela',
 1237: 	'3,2' => 'prima hermana una vez removida',
 1238: 	'3,3' => 'prima segunda',
 1239: 	'3,4' => 'prima segunda una vez removida',
 1240: 	'3,5' => 'prima segunda dos veces removida',
 1241: 	'3,6' => 'prima segunda tres veces removida',
 1242: 	'3,7' => 'prima segunda cuatro veces removida',
 1243: 	'3,8' => 'prima segunda cinco veces removida',
 1244: 	'3,9' => 'prima segunda seis veces removida',
 1245: 	'3,10' => 'prima segunda siete veces removida',
 1246: 	'4,0' => 'tatarabuela',
 1247: 	'4,1' => 'tia bisabuela',
 1248: 	'4,2' => 'prima hermana dos veces removida',
 1249: 	'4,3' => 'prima segunda una vez removida',
 1250: 	'4,4' => 'prima tercera',
 1251: 	'4,5' => 'prima tercera una vez removida',
 1252: 	'4,6' => 'prima tercera dos veces removida',
 1253: 	'4,7' => 'prima tercera tres veces removida',
 1254: 	'4,8' => 'prima tercera cuatro veces removida',
 1255: 	'4,9' => 'prima tercera cinco veces removida',
 1256: 	'4,10' => 'prima tercera seis veces removida',
 1257: 	'5,0' => 'chozna',
 1258: 	'5,1' => 'tia tatarabuela',
 1259: 	'5,2' => 'prima hermana tres veces removida',
 1260: 	'5,3' => 'prima segunda dos veces removida',
 1261: 	'5,4' => 'prima tercera una vez removida',
 1262: 	'5,5' => 'prima cuarta',
 1263: 	'5,6' => 'prima cuarta una vez removida',
 1264: 	'5,7' => 'prima cuarta dos veces removida',
 1265: 	'5,8' => 'prima cuarta tres veces removida',
 1266: 	'5,9' => 'prima cuarta cuatro veces removida',
 1267: 	'5,10' => 'prima cuarta cinco veces removida',
 1268: 	'6,0' => 'bisabuela quinta',
 1269: 	'6,1' => 'tia lejana',
 1270: 	'6,2' => 'prima hermana cuatro veces removida',
 1271: 	'6,3' => 'prima segunda tres veces removida',
 1272: 	'6,4' => 'prima tercera dos veces removida',
 1273: 	'6,5' => 'prima cuarta una vez removida',
 1274: 	'6,6' => 'prima quinta',
 1275: 	'6,7' => 'prima quinta una vez removida',
 1276: 	'6,8' => 'prima quinta dos veces removida',
 1277: 	'6,9' => 'prima quinta tres veces removida',
 1278: 	'6,10' => 'prima quinta cuatro veces removida',
 1279: 	'7,0' => 'antepasada lejana',
 1280: 	'7,1' => 'tia lejana',
 1281: 	'7,2' => 'prima hermana cinco veces removida',
 1282: 	'7,3' => 'prima segunda cuatro veces removida',
 1283: 	'7,4' => 'prima tercera tres veces removida',
 1284: 	'7,5' => 'prima cuarta dos veces removida',
 1285: 	'7,6' => 'prima quinta una vez removida',
 1286: 	'7,7' => 'prima sexta',
 1287: 	'7,8' => 'prima sexta una vez removida',
 1288: 	'7,9' => 'prima sexta dos veces removida',
 1289: 	'7,10' => 'prima sexta tres veces removida',
 1290: 	'8,0' => 'antepasada lejana',
 1291: 	'8,1' => 'tia lejana',
 1292: 	'8,2' => 'prima hermana seis veces removida',
 1293: 	'8,3' => 'prima segunda cinco veces removida',
 1294: 	'8,4' => 'prima tercera cuatro veces removida',
 1295: 	'8,5' => 'prima cuarta tres veces removida',
 1296: 	'8,6' => 'prima quinta dos veces removida',
 1297: 	'8,7' => 'prima sexta una vez removida',
 1298: 	'8,8' => 'prima septima',
 1299: 	'8,9' => 'prima septima una vez removida',
 1300: 	'8,10' => 'prima septima dos veces removida',
 1301: 	'9,0' => 'antepasada lejana',
 1302: 	'9,1' => 'tia lejana',
 1303: 	'9,2' => 'prima hermana siete veces removida',
 1304: 	'9,3' => 'prima segunda seis veces removida',
 1305: 	'9,4' => 'prima tercera cinco veces removida',
 1306: 	'9,5' => 'prima cuarta cuatro veces removida',
 1307: 	'9,6' => 'prima quinta tres veces removida',
 1308: 	'9,7' => 'prima sexta dos veces removida',
 1309: 	'9,8' => 'prima septima una vez removida',
 1310: 	'9,9' => 'prima octava',
 1311: 	'9,10' => 'prima octava una vez removida',
 1312: 	'10,0' => 'antepasada lejana',
 1313: 	'10,1' => 'tia lejana',
 1314: 	'10,2' => 'prima hermana ocho veces removida',
 1315: 	'10,3' => 'prima segunda siete veces removida',
 1316: 	'10,4' => 'prima tercera seis veces removida',
 1317: 	'10,5' => 'prima cuarta cinco veces removida',
 1318: 	'10,6' => 'prima quinta cuatro veces removida',
 1319: 	'10,7' => 'prima sexta tres veces removida',
 1320: 	'10,8' => 'prima septima dos veces removida',
 1321: 	'10,9' => 'prima octava una vez removida',
 1322: 	'10,10' => 'prima novena',
 1323: );
 1324: 
 1325: # ---------------------------------------------------------------------------
 1326: # Farsi (Persian) relationship tables
 1327: # Values use \N{U+XXXX} Unicode escapes (right-to-left script)
 1328: # Side-specific keys: "s1,s2,paternal" / "s1,s2,maternal"
 1329: # ---------------------------------------------------------------------------
 1330: 
 1331: Readonly::Hash my %FA_MALE_RELATIONSHIPS => (
 1332: 	'0,0' => "\N{U+062E}\N{U+0648}\N{U+062F}",
 1333: 	'0,1' => "\N{U+067E}\N{U+0633}\N{U+0631}",
 1334: 	'0,2' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1335: 	'0,3' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1336: 	'0,4' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1337: 	'0,5' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1338: 	'0,6' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1339: 	'0,7' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1340: 	'0,8' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1341: 	'0,9' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1342: 	'0,10' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1343: 	'1,0' => "\N{U+067E}\N{U+062F}\N{U+0631}",
 1344: 	'1,1' => "\N{U+0628}\N{U+0631}\N{U+0627}\N{U+062F}\N{U+0631}",
 1345: 	'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}",
 1346: 	'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}",
 1347: 	'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}",
 1348: 	'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}",
 1349: 	'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}",
 1350: 	'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}",
 1351: 	'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}",
 1352: 	'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}",
 1353: 	'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}",
 1354: 	'2,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1355: 	'2,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1356: 	'2,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1357: 	'2,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1358: 	'2,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1359: 	'2,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1360: 	'2,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1361: 	'2,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1362: 	'2,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1363: 	'2,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1364: 	'2,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1365: 	'3,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1366: 	'3,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1367: 	'3,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1368: 	'3,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1369: 	'3,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1370: 	'3,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1371: 	'3,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1372: 	'3,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1373: 	'3,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1374: 	'3,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1375: 	'3,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1376: 	'4,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1377: 	'4,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1378: 	'4,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1379: 	'4,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1380: 	'4,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1381: 	'4,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1382: 	'4,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1383: 	'4,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1384: 	'4,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1385: 	'4,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1386: 	'4,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1387: 	'5,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1388: 	'5,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1389: 	'5,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1390: 	'5,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1391: 	'5,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1392: 	'5,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1393: 	'5,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1394: 	'5,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1395: 	'5,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1396: 	'5,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1397: 	'5,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1398: 	'6,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1399: 	'6,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1400: 	'6,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1401: 	'6,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1402: 	'6,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1403: 	'6,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1404: 	'6,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1405: 	'6,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1406: 	'6,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1407: 	'6,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1408: 	'6,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1409: 	'7,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1410: 	'7,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1411: 	'7,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1412: 	'7,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1413: 	'7,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1414: 	'7,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1415: 	'7,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1416: 	'7,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1417: 	'7,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1418: 	'7,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1419: 	'7,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1420: 	'8,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1421: 	'8,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1422: 	'8,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1423: 	'8,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1424: 	'8,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1425: 	'8,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1426: 	'8,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1427: 	'8,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1428: 	'8,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1429: 	'8,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1430: 	'8,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1431: 	'9,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1432: 	'9,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1433: 	'9,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1434: 	'9,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1435: 	'9,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1436: 	'9,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1437: 	'9,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1438: 	'9,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1439: 	'9,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1440: 	'9,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1441: 	'9,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1442: 	'10,0' => "\N{U+067E}\N{U+062F}\N{U+0631}\N{U+0628}\N{U+0632}\N{U+0631}\N{U+06AF}",
 1443: 	'10,1' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1444: 	'10,2' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1445: 	'10,3' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1446: 	'10,4' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1447: 	'10,5' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1448: 	'10,6' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1449: 	'10,7' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1450: 	'10,8' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1451: 	'10,9' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1452: 	'10,10' => "\N{U+067E}\N{U+0633}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1453: 	'2,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1454: 	'2,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1455: 	'3,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1456: 	'3,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1457: 	'4,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1458: 	'4,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1459: 	'5,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1460: 	'5,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1461: 	'6,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1462: 	'6,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1463: 	'7,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1464: 	'7,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1465: 	'8,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1466: 	'8,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1467: 	'9,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1468: 	'9,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1469: 	'10,1,maternal' => "\N{U+062F}\N{U+0627}\N{U+06CC}\N{U+06CC}",
 1470: 	'10,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0648}",
 1471: );
 1472: 
 1473: Readonly::Hash my %FA_FEMALE_RELATIONSHIPS => (
 1474: 	'0,0' => "\N{U+062E}\N{U+0648}\N{U+062F}",
 1475: 	'0,1' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}",
 1476: 	'0,2' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1477: 	'0,3' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1478: 	'0,4' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1479: 	'0,5' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1480: 	'0,6' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1481: 	'0,7' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1482: 	'0,8' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1483: 	'0,9' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1484: 	'0,10' => "\N{U+0646}\N{U+0648}\N{U+0647}",
 1485: 	'1,0' => "\N{U+0645}\N{U+0627}\N{U+062F}\N{U+0631}",
 1486: 	'1,1' => "\N{U+062E}\N{U+0648}\N{U+0627}\N{U+0647}\N{U+0631}",
 1487: 	'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}",
 1488: 	'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}",
 1489: 	'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}",
 1490: 	'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}",
 1491: 	'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}",
 1492: 	'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}",
 1493: 	'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}",
 1494: 	'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}",
 1495: 	'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}",
 1496: 	'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}",
 1497: 	'2,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1498: 	'2,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1499: 	'2,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1500: 	'2,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1501: 	'2,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1502: 	'2,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1503: 	'2,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1504: 	'2,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1505: 	'2,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1506: 	'2,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1507: 	'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}",
 1508: 	'3,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1509: 	'3,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1510: 	'3,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1511: 	'3,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1512: 	'3,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1513: 	'3,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1514: 	'3,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1515: 	'3,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1516: 	'3,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1517: 	'3,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1518: 	'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}",
 1519: 	'4,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1520: 	'4,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1521: 	'4,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1522: 	'4,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1523: 	'4,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1524: 	'4,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1525: 	'4,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1526: 	'4,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1527: 	'4,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1528: 	'4,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1529: 	'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}",
 1530: 	'5,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1531: 	'5,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1532: 	'5,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1533: 	'5,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1534: 	'5,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1535: 	'5,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1536: 	'5,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1537: 	'5,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1538: 	'5,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1539: 	'5,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1540: 	'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}",
 1541: 	'6,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1542: 	'6,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1543: 	'6,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1544: 	'6,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1545: 	'6,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1546: 	'6,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1547: 	'6,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1548: 	'6,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1549: 	'6,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1550: 	'6,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1551: 	'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}",
 1552: 	'7,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1553: 	'7,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1554: 	'7,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1555: 	'7,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1556: 	'7,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1557: 	'7,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1558: 	'7,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1559: 	'7,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1560: 	'7,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1561: 	'7,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1562: 	'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}",
 1563: 	'8,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1564: 	'8,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1565: 	'8,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1566: 	'8,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1567: 	'8,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1568: 	'8,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1569: 	'8,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1570: 	'8,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1571: 	'8,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1572: 	'8,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1573: 	'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}",
 1574: 	'9,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1575: 	'9,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1576: 	'9,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1577: 	'9,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1578: 	'9,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1579: 	'9,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1580: 	'9,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1581: 	'9,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1582: 	'9,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1583: 	'9,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1584: 	'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}",
 1585: 	'10,1' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1586: 	'10,2' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1587: 	'10,3' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1588: 	'10,4' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1589: 	'10,5' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1590: 	'10,6' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1591: 	'10,7' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1592: 	'10,8' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1593: 	'10,9' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1594: 	'10,10' => "\N{U+062F}\N{U+062E}\N{U+062A}\N{U+0631}\N{U+0639}\N{U+0645}\N{U+0648}",
 1595: 	'2,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1596: 	'2,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1597: 	'3,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1598: 	'3,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1599: 	'4,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1600: 	'4,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1601: 	'5,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1602: 	'5,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1603: 	'6,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1604: 	'6,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1605: 	'7,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1606: 	'7,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1607: 	'8,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1608: 	'8,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1609: 	'9,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1610: 	'9,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1611: 	'10,1,maternal' => "\N{U+062E}\N{U+0627}\N{U+0644}\N{U+0647}",
 1612: 	'10,1,paternal' => "\N{U+0639}\N{U+0645}\N{U+0647}",
 1613: );
 1614: 
 1615: # ---------------------------------------------------------------------------
 1616: # Classical Latin relationship tables
 1617: # Many step-count combinations have no classical term; those keys are absent.
 1618: # Side-specific keys: "s1,s2,paternal" / "s1,s2,maternal"
 1619: # ---------------------------------------------------------------------------
 1620: 
 1621: Readonly::Hash my %LA_MALE_RELATIONSHIPS => (
 1622: 	'0,0' => 'ipse',
 1623: 	'0,1' => 'filius',
 1624: 	'0,2' => 'nepos',
 1625: 	'0,3' => 'pronepos',
 1626: 	'0,4' => 'abnepos',
 1627: 	'0,5' => 'atnepos',
 1628: 	'0,6' => 'trinepos',
 1629: 	'1,0' => 'pater',
 1630: 	'1,1' => 'frater',
 1631: 	'1,2' => 'nepos',
 1632: 	'2,0' => 'avus',
 1633: 	'2,1' => 'patruus',
 1634: 	'2,2' => 'consobrinus',
 1635: 	'3,0' => 'proavus',
 1636: 	'3,1' => 'patruus magnus',
 1637: 	'4,0' => 'abavus',
 1638: 	'4,1' => 'patruus maior',
 1639: 	'5,0' => 'atavus',
 1640: 	'5,1' => 'patruus maximus',
 1641: 	'6,0' => 'tritavus',
 1642: 	'2,1,maternal' => 'avunculus',
 1643: 	'2,1,paternal' => 'patruus',
 1644: 	'2,2,maternal' => 'consobrinus',
 1645: 	'2,2,paternal' => 'patruelis',
 1646: 	'3,1,maternal' => 'avunculus magnus',
 1647: 	'3,1,paternal' => 'patruus magnus',
 1648: 	'4,1,maternal' => 'avunculus maior',
 1649: 	'4,1,paternal' => 'patruus maior',
 1650: 	'5,1,maternal' => 'avunculus maximus',
 1651: 	'5,1,paternal' => 'patruus maximus',
 1652: );
 1653: 
 1654: Readonly::Hash my %LA_FEMALE_RELATIONSHIPS => (
 1655: 	'0,0' => 'ipsa',
 1656: 	'0,1' => 'filia',
 1657: 	'0,2' => 'neptis',
 1658: 	'0,3' => 'proneptis',
 1659: 	'0,4' => 'abneptis',
 1660: 	'0,5' => 'atneptis',
 1661: 	'0,6' => 'trineptis',
 1662: 	'1,0' => 'mater',
 1663: 	'1,1' => 'soror',
 1664: 	'1,2' => 'neptis',
 1665: 	'2,0' => 'avia',
 1666: 	'2,1' => 'amita',
 1667: 	'2,2' => 'consobrina',
 1668: 	'3,0' => 'proavia',
 1669: 	'3,1' => 'amita magna',
 1670: 	'4,0' => 'abavia',
 1671: 	'4,1' => 'amita maior',
 1672: 	'5,0' => 'atavia',
 1673: 	'5,1' => 'amita maxima',
 1674: 	'6,0' => 'tritavia',
 1675: 	'2,1,maternal' => 'matertera',
 1676: 	'2,1,paternal' => 'amita',
 1677: 	'2,2,maternal' => 'consobrina',
 1678: 	'2,2,paternal' => 'patruelis',
 1679: 	'3,1,maternal' => 'matertera magna',
 1680: 	'3,1,paternal' => 'amita magna',
 1681: 	'4,1,maternal' => 'matertera maior',
 1682: 	'4,1,paternal' => 'amita maior',
 1683: 	'5,1,maternal' => 'matertera maxima',
 1684: 	'5,1,paternal' => 'amita maxima',
 1685: );
 1686: 
 1687: # ---------------------------------------------------------------------------
 1688: # Master dispatch table: lang -> sex -> hashref
 1689: # ---------------------------------------------------------------------------
 1690: 
 1691: Readonly::Hash my %RELATIONSHIP_TABLES => (
 1692: 	'en' => {
 1693: 		$SEX_MALE   => \%EN_MALE_RELATIONSHIPS,
 1694: 		$SEX_FEMALE => \%EN_FEMALE_RELATIONSHIPS,
 1695: 	}, 'es' => {
 1696: 		$SEX_MALE   => \%ES_MALE_RELATIONSHIPS,
 1697: 		$SEX_FEMALE => \%ES_FEMALE_RELATIONSHIPS,
 1698: 	}, 'fa' => {
 1699: 		$SEX_MALE   => \%FA_MALE_RELATIONSHIPS,
 1700: 		$SEX_FEMALE => \%FA_FEMALE_RELATIONSHIPS,
 1701: 	}, 'fr' => {
 1702: 		$SEX_MALE   => \%FR_MALE_RELATIONSHIPS,
 1703: 		$SEX_FEMALE => \%FR_FEMALE_RELATIONSHIPS,
 1704: 	}, 'de' => {
 1705: 		$SEX_MALE   => \%DE_MALE_RELATIONSHIPS,
 1706: 		$SEX_FEMALE => \%DE_FEMALE_RELATIONSHIPS,
 1707: 	}, 'de_ch' => {
 1708: 		$SEX_MALE   => \%DE_CH_MALE_RELATIONSHIPS,
 1709: 		$SEX_FEMALE => \%DE_CH_FEMALE_RELATIONSHIPS,
 1710: 	}, 'la' => {
 1711: 		$SEX_MALE   => \%LA_MALE_RELATIONSHIPS,
 1712: 		$SEX_FEMALE => \%LA_FEMALE_RELATIONSHIPS,
 1713: 	},
 1714: );
 1715: # ---------------------------------------------------------------------------
 1716: # Constructor
 1717: # ---------------------------------------------------------------------------
 1718: 
 1719: =head1 NAME
 1720: 
 1721: Genealogy::Relationship::Name - Return a genealogical relationship name from step counts
 1722: 
 1723: =head1 VERSION
 1724: 
 1725: Version 0.03
 1726: 
 1727: =head1 SYNOPSIS
 1728: 
 1729:     use Genealogy::Relationship::Name;
 1730: 
 1731:     my $namer = Genealogy::Relationship::Name->new();
 1732: 
 1733:     my $name = $namer->name(
 1734:         steps_to_ancestor   => 2,
 1735:         steps_from_ancestor => 3,
 1736:         sex                 => 'F',
 1737:     );
 1738:     # Returns 'first cousin once-removed'
 1739: 
 1740:     # With language
 1741:     my $name_fr = $namer->name(
 1742:         steps_to_ancestor   => 2,
 1743:         steps_from_ancestor => 2,
 1744:         sex                 => 'M',
 1745:         language            => 'fr',
 1746:     );
 1747:     # Returns 'cousin germain'
 1748: 
 1749: =head1 DESCRIPTION
 1750: 
 1751: C<Genealogy::Relationship::Name> maps a pair of step-counts (person A to common
 1752: ancestor, common ancestor to person B) plus the sex of person B and an optional
 1753: language code to a human-readable relationship name string.
 1754: 
 1755: The relationship tables were originally embedded in the C<gedcom> and C<ged2site>
 1756: distributions inside C<Gedcom::Individual::relationship_up()>; this module
 1757: extracts them into a reusable, installable CPAN distribution.
 1758: 
 1759: Supported languages: C<en> (English, default), C<de> (German), C<es> (Spanish),
 1760: C<fa> (Farsi/Persian), C<fr> (French), C<la> (Classical Latin).
 1761: 
 1762: =head1 METHODS
 1763: 
 1764: =head2 new
 1765: 
 1766: Constructor.  Creates and returns a blessed C<Genealogy::Relationship::Name>
 1767: object.
 1768: 
 1769: =head3 PURPOSE
 1770: 
 1771: Initialises the object with optional configuration: a default language for
 1772: subsequent C<name()> calls, and an optional L<Log::Abstraction> object to
 1773: use as the error logger.  Configuration may also be loaded from an INI-style
 1774: file via L<Object::Configure>.
 1775: 
 1776: =head3 ARGUMENTS
 1777: 
 1778: =over 4
 1779: 
 1780: =item C<language> (string, optional)
 1781: 
 1782: Default BCP-47 language tag (primary subtag only) for all C<name()> calls
 1783: on this object.  Supported values: C<en> (default), C<fr>, C<de>.  May be
 1784: overridden per-call by passing C<language> to C<name()>.
 1785: 
 1786: =item C<logger>
 1787: 
 1788: A pre-constructed loggining object.  When a required argument is
 1789: passed as C<undef> to C<name()>, the error is reported via
 1790: C<< $logger->error($msg) >> rather than C<croak>.  This allows
 1791: programs to route errors through their own
 1792: infrastructure with full C<ctx> context.
 1793: 
 1794: See L<Log::Abstraction> and the L</CONFIGURATION> section for the
 1795: recommended construction pattern.
 1796: 
 1797: =item C<config_file> (string, optional)
 1798: 
 1799: Path to an INI-style configuration file processed by L<Object::Configure>.
 1800: Any keys it sets may be overridden by arguments passed directly to C<new()>.
 1801: 
 1802: =back
 1803: 
 1804: =head3 RETURNS
 1805: 
 1806: A blessed C<Genealogy::Relationship::Name> object.
 1807: 
 1808: =head3 SIDE EFFECTS
 1809: 
 1810: Calls L<Object::Configure> C<configure()>, which may read from a
 1811: configuration file on disk if C<config_file> is supplied or if a default
 1812: configuration file exists for the class.
 1813: 
 1814: =head3 NOTES
 1815: 
 1816: L<Object::Configure> cannot handle object or coderef values (it treats
 1817: unknown scalar values as configuration file paths).  The C<logger> key is
 1818: therefore stashed before the C<configure()> call and restored afterward.
 1819: Any future object-valued constructor arguments must follow the same pattern.
 1820: 
 1821: =head3 EXAMPLE
 1822: 
 1823:     use Genealogy::Relationship::Name;
 1824:     use Log::Abstraction;
 1825: 
 1826:     # Minimal construction
 1827:     my $namer = Genealogy::Relationship::Name->new();
 1828: 
 1829:     # With a default language
 1830:     my $namer_fr = Genealogy::Relationship::Name->new(language => 'fr');
 1831: 
 1832:     # With a Log::Abstraction logger
 1833:     my $la = Log::Abstraction->new(
 1834:         logger => sub {
 1835:             my $args = shift;
 1836:             my $msg = $args->{ctx}
 1837:                 ? $args->{ctx}->as_string() . ': ' . join('', @{$args->{message}})
 1838:                 : join('', @{$args->{message}});
 1839:             complain({ message => $msg, person => $args->{ctx} });
 1840:         },
 1841:         ctx => $individual,
 1842:     );
 1843:     my $namer = Genealogy::Relationship::Name->new(language => 'en', logger => $la);
 1844: 
 1845: =head3 API SPECIFICATION
 1846: 
 1847: =head4 Input
 1848: 
 1849:     {
 1850: 	language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 },
 1851:         logger   => { type => 'object', optional => 1 },
 1852:     }
 1853: 
 1854: =head4 Output
 1855: 
 1856:     {
 1857:         type  => 'object',
 1858:         class => 'Genealogy::Relationship::Name',
 1859:     }
 1860: 
 1861: =cut
 1862: 
 1863: sub new {
 1864: 	# Create and return a blessed object
1865 → 1873 → 1879 1865: 	my $class = shift;
 1866: 
 1867: 	# Handle hash or hashref arguments
 1868: 	my $params = Params::Get::get_params(undef, \@_);
 1869: 
 1870: 	# Stash keys that are coderefs or objects before passing to Object::Configure,
 1871: 	# which cannot handle them (it treats unknown scalar values as config file paths)
 1872: 	my %stash;
 1873: 	for my $key (qw(logger)) {
 1874: 		next unless exists $params->{$key};
 1875: 		$stash{$key} = delete $params->{$key};
 1876: 	}
 1877: 
 1878: 	# Load the configuration from a config file, if provided
 1879: 	$params = Object::Configure::configure($class, $params);
 1880: 
 1881: 	# Restore the stashed coderefs and objects after configure()
 1882: 	@{$params}{keys %stash} = values %stash;
 1883: 
 1884: 	# Bless and return the object; logger/ctx/level keys from params

Mutants (Total: 2, Killed: 2, Survived: 0)

1885: # are stored directly and accessed via $self->{logger} etc. 1886: return bless { 1887: # Store any constructor-time config for Object::Configure compatibility 1888: %{$params}, 1889: }, ref($class) || $class; 1890: } 1891: 1892: # --------------------------------------------------------------------------- 1893: # Public method: name() 1894: # --------------------------------------------------------------------------- 1895: 1896: =head2 name 1897: 1898: Returns the name of the relationship between person A and person B. 1899: 1900: =head3 PURPOSE 1901: 1902: Given the number of steps from person A up to the nearest common ancestor 1903: (C<steps_to_ancestor>) and the number of steps from that ancestor down to 1904: person B (C<steps_from_ancestor>), plus the sex of person B and a language 1905: code, returns a localised relationship-name string. 1906: 1907: =head3 ARGUMENTS 1908: 1909: =over 4 1910: 1911: =item C<steps_to_ancestor> (integer, required) 1912: 1913: Number of generational steps from person A up to the common ancestor. 1914: Must be a non-negative integer. Zero means person A I<is> the ancestor. 1915: 1916: =item C<steps_from_ancestor> (integer, required) 1917: 1918: Number of generational steps from the common ancestor down to person B. 1919: Must be a non-negative integer. 1920: 1921: =item C<sex> (string, required) 1922: 1923: Sex of person B. Must be C<'M'> (male) or C<'F'> (female). 1924: 1925: =item C<language> (string, optional) 1926: 1927: BCP-47-style language tag (only the primary subtag is used). 1928: Supported values: C<en> (default), C<de>, C<es>, C<fa>, C<fr>, C<la>. 1929: 1930: Note: C<fa> (Farsi/Persian) values are stored as C<\N{U+XXXX}> Unicode 1931: escapes and render correctly in any Unicode-aware context. C<la> 1932: (Classical Latin) has a sparse table; many step-count combinations have 1933: no classical term and return C<undef>. 1934: 1935: =item C<person> (object, optional) 1936: 1937: An optional person object (e.g. a C<Gedcom::Individual> instance) passed 1938: through to the error handler when an error occurs. Takes priority over the 1939: C<ctx> set at construction time. The handler receives it as C<ctx> (logger 1940: path) or C<person> (on_error path), matching the C<complain()> interface 1941: in C<gedcom>/C<ged2site>. 1942: 1943: =item C<family_side> (string, optional) 1944: 1945: C<'paternal'> or C<'maternal'>. Used by languages that distinguish the 1946: paternal from the maternal line for the same step counts. Currently 1947: relevant for: 1948: 1949: =over 4 1950: 1951: =item * C<la> (Latin) -- uncle/aunt (C<patruus>/C<avunculus>, 1952: C<amita>/C<matertera>) and first cousin (C<patruelis>/C<consobrinus>) 1953: 1954: =item * C<fa> (Farsi) -- uncle (C<amoo>/C<dayi>) and aunt 1955: (C<ammeh>/C<khaleh>) 1956: 1957: =back 1958: 1959: When C<family_side> is not supplied, the table falls back to the generic 1960: (non-side-specific) entry for that step-count pair. 1961: 1962: =back 1963: 1964: =head3 RETURNS 1965: 1966: A string containing the relationship name, or C<undef> if the combination 1967: is not found in the lookup table. 1968: 1969: =head3 EXAMPLE 1970: 1971: my $namer = Genealogy::Relationship::Name->new(); 1972: 1973: # Person A is the grandparent (2 steps up) of the common ancestor, 1974: # and person B is 3 steps below the ancestor; B is female => first cousin once-removed 1975: my $rel = $namer->name( 1976: steps_to_ancestor => 2, 1977: steps_from_ancestor => 3, 1978: sex => 'F', 1979: ); 1980: 1981: =head3 API SPECIFICATION 1982: 1983: =head4 Input 1984: 1985: { 1986: steps_to_ancestor => { type => 'integer', minimum => 0 }, 1987: steps_from_ancestor => { type => 'integer', minimum => 0 }, 1988: sex => { type => 'string', memberof => ['M', 'F'] }, 1989: language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 }, 1990: # person is handled before validate_strict (PVS infers constraints from objects) 1991: family_side => { type => 'string', memberof => ['paternal','maternal'], optional => 1 }, 1992: } 1993: 1994: =head4 Output 1995: 1996: { 1997: type => 'string', 1998: optional => 1, # undef when the combination is not tabulated 1999: } 2000: 2001: =head3 FORMAL SPECIFICATION 2002: 2003: name ______________________________________________________ 2004: [In] steps_to_ancestor : N0 2005: steps_from_ancestor : N0 2006: sex : {M, F} 2007: language : {en, es, fa, fr, de, la}? (default en) 2008: person : Object? 2009: [Out] result : String | undef 2010: 2011: Let key == steps_to_ancestor ++ "," ++ steps_from_ancestor 2012: Let side_key == key ++ "," ++ family_side if family_side defined 2013: Let table == RELATIONSHIP_TABLES(language)(sex) 2014: result == table(side_key) if family_side defined and side_key in dom table 2015: == table(key) if key in dom table 2016: == undef otherwise 2017: 2018: =cut 2019: 2020: sub name { 2021 → 2039 → 2047 2021: my $self = shift; 2022: 2023: # Validate and extract the remaining parameters; capture the return value 2024: my $args = Params::Validate::Strict::validate_strict( 2025: args => Params::Get::get_params(undef, \@_) || {}, 2026: schema => { 2027: steps_to_ancestor => { type => 'integer', minimum => 0 }, 2028: steps_from_ancestor => { type => 'integer', minimum => 0 }, 2029: sex => { type => 'string', memberof => ['M', 'F'] }, 2030: language => { type => 'string', regex => qr/^(?:en|de(?:-ch)?|es|fa|fr|la)/, optional => 1 }, 2031: person => { type => 'object', optional => 1 }, 2032: family_side => { type => 'string', memberof => ['paternal','maternal'], 2033: optional => 1 }, 2034: } 2035: ); 2036: 2037: # Extract individual parameters; undef means arg was given as undef, so 2038: # report via logger if set, otherwise croak

Mutants (Total: 1, Killed: 1, Survived: 0)

2039: foreach my $arg(qw(steps_to_ancestor steps_from_ancestor sex)) {

Mutants (Total: 1, Killed: 1, Survived: 0)

2040: if(!defined($args->{$arg})) { 2041: if(my $logger = $self->{logger}) { 2042: $logger->error("$arg not given"); 2043: } 2044: croak("$arg not given"); 2045: } 2046: } 2047 → 2058 → 2067 2047: my $steps1 = $args->{steps_to_ancestor}; 2048: my $steps2 = $args->{steps_from_ancestor}; 2049: my $sex = $args->{sex}; 2050: my $person = $args->{person}; 2051: my $family_side = $args->{family_side}; 2052: 2053: # Fall back to constructor default or hard default if no per-call language given 2054: my $lang = lc($args->{language} // $self->{language} // $DEFAULT_LANGUAGE); 2055: 2056: # Swiss German (de-CH) maps to its own table before subtag stripping,

Mutants (Total: 1, Killed: 1, Survived: 0)

2057: # because it uses 'ss' where standard German uses Eszett 2058: if($lang eq 'de-ch') { 2059: $lang = 'de_ch'; 2060: } else { 2061: # Strip any region subtag (e.g. 'en-GB' -> 'en') after lowercasing 2062: ($lang) = split /-/, $lang; 2063: } 2064: 2065: # Build lookup key from the two step counts; try side-specific key first 2066: # for languages that distinguish paternal/maternal (Latin, Farsi) 2067: my $key = "${steps1},${steps2}"; 2068: my $side_key = defined($family_side) ? "${key},${family_side}" : undef; 2069: 2070: # Retrieve the correct gender-specific table for the chosen language 2071: my $table = $RELATIONSHIP_TABLES{$lang}{$sex}; 2072: 2073: # Prefer side-specific entry when family_side is given; fall back to generic key 2074: my $result = (defined($side_key) && exists $table->{$side_key}) 2075: ? $table->{$side_key} 2076: : $table->{$key};

Mutants (Total: 2, Killed: 2, Survived: 0)

2077: 2078: return $result; 2079: } 2080: 2081: # --------------------------------------------------------------------------- 2082: # Public method: supported_languages() 2083: # --------------------------------------------------------------------------- 2084: 2085: =head2 supported_languages 2086: 2087: Returns a sorted list of the language codes that the module supports. 2088: 2089: =head3 PURPOSE 2090: 2091: Allows calling code to enumerate the languages available for C<name()> 2092: without hard-coding them. 2093: 2094: =head3 ARGUMENTS 2095: 2096: None. 2097: 2098: =head3 RETURNS 2099: 2100: A list (or array-ref in scalar context) of language code strings, 2101: currently C<('de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la')>. 2102: 2103: =head3 EXAMPLE 2104: 2105: my @langs = $namer->supported_languages(); 2106: # ( 'de', 'de_ch', 'en', 'es', 'fa', 'fr', 'la' ) 2107: 2108: =head3 API SPECIFICATION 2109: 2110: =head4 Input 2111: 2112: {} # no arguments 2113: 2114: =head4 Output 2115: 2116: { 2117: type => ARRAYREF, # sorted list of language codes 2118: } 2119: 2120: =cut 2121: 2122: sub supported_languages { 2123: # Return the sorted set of keys from the master dispatch table

Mutants (Total: 2, Killed: 2, Survived: 0)

2124: my @langs = sort keys %RELATIONSHIP_TABLES; 2125: return wantarray ? @langs : \@langs; 2126: } 2127: 2128: # --------------------------------------------------------------------------- 2129: # Public method: known_sexes() 2130: # --------------------------------------------------------------------------- 2131: 2132: =head2 known_sexes 2133: 2134: Returns the list of sex codes accepted by C<name()>. 2135: 2136: =head3 PURPOSE 2137: 2138: Documents and exposes the set of valid C<sex> values so that callers can 2139: validate their own input without duplicating knowledge. 2140: 2141: =head3 ARGUMENTS 2142: 2143: None. 2144: 2145: =head3 RETURNS 2146: 2147: A list (or array-ref in scalar context) of valid sex code strings: C<('F', 'M')>. 2148: 2149: =head3 SIDE EFFECTS 2150: 2151: None. 2152: 2153: =head3 EXAMPLE 2154: 2155: my @sexes = $namer->known_sexes(); 2156: # ( 'F', 'M' ) 2157: 2158: =head3 API SPECIFICATION 2159: 2160: =head4 Input 2161: 2162: {} # no arguments 2163: 2164: =head4 Output 2165: 2166: { 2167: type => ARRAYREF, 2168: } 2169: 2170: =cut 2171: 2172: sub known_sexes { 2173: # Return the two valid sex codes in sorted order

Mutants (Total: 2, Killed: 2, Survived: 0)

2174: my @sexes = sort($SEX_FEMALE, $SEX_MALE); 2175: return wantarray ? @sexes : \@sexes; 2176: } 2177: 2178: 1; 2179: 2180: __END__ 2181: 2182: =head1 CONFIGURATION 2183: 2184: The constructor accepts an optional C<language> key which sets the default 2185: language for all subsequent calls to C<name()>: 2186: 2187: my $namer = Genealogy::Relationship::Name->new(language => 'fr'); 2188: 2189: This default can be overridden per-call by passing C<language> to C<name()>. 2190: The object is also compatible with C<Object::Configure> for runtime 2191: reconfiguration. 2192: 2193: =head2 Error handling 2194: 2195: Errors are dispatched through the following priority chain: 2196: 2197: =over 4 2198: 2199: =item 1. L<Log::Abstraction> object (preferred) 2200: 2201: Construct a C<Log::Abstraction> object with the desired logger coderef and 2202: C<ctx> (typically a C<Gedcom::Individual>), then pass it as C<logger> to 2203: C<new()>. On error, this module simply calls C<< $logger->error($msg) >> 2204: and Log::Abstraction handles ctx forwarding, formatting, and dispatch. 2205: 2206: use Log::Abstraction; 2207: 2208: my $logger = Log::Abstraction->new( 2209: logger => sub { 2210: my $args = shift; 2211: my $msg = $args->{ctx} 2212: ? $args->{ctx}->as_string() . ': ' . join('', @{$args->{message}}) 2213: : join('', @{$args->{message}}); 2214: complain({ message => $msg, person => $args->{ctx} }); 2215: }, 2216: ctx => $individual, 2217: ); 2218: 2219: my $namer = Genealogy::Relationship::Name->new(logger => $logger); 2220: 2221: =back 2222: 2223: If any handler returns without dying (e.g. a warning-only handler in 2224: L<Log::Abstraction>), C<name()> returns C<undef>. 2225: 2226: =head1 DIAGNOSTICS 2227: 2228: =over 4 2229: 2230: =item steps_to_ancestor not given 2231: 2232: C<steps_to_ancestor> was passed as C<undef>. Passing C<undef> explicitly is 2233: distinct from omitting the argument; use a defined non-negative integer. 2234: 2235: =item steps_from_ancestor not given 2236: 2237: As above, for C<steps_from_ancestor>. 2238: 2239: =item sex not given 2240: 2241: C<sex> was passed as C<undef>. Supply C<'M'> or C<'F'>. 2242: 2243: =back 2244: 2245: =head1 DEPENDENCIES 2246: 2247: L<Carp>, L<Object::Configure> 2248: 2249: Optionally L<Log::Abstraction> (E<gt>= 0.28) for the C<logger>/C<ctx> error 2250: dispatch path. 2251: L<Params::Get>, L<Params::Validate::Strict>, L<Readonly> 2252: 2253: =head1 BUGS AND LIMITATIONS 2254: 2255: The lookup tables currently cover steps 0-6 in both directions. Relationships 2256: further removed (seventh cousin, etc.) return C<undef>. Pull requests adding 2257: deeper tables are welcome. 2258: 2259: =head1 TODO 2260: 2261: =over 4 2262: 2263: =item * Extract and integrate the Latin relationship handling code currently 2264: embedded in the C<gedcom> and C<ged2site> programs, adding C<la> as a 2265: supported language alongside C<en>, C<fr>, and C<de>. 2266: 2267: =back 2268: 2269: =head1 SEE ALSO 2270: 2271: =over 4 2272: 2273: =item * L<Configure an Object at Runtime|Object::Configure> 2274: 2275: =item * L<Test Dashboard|https://nigelhorne.github.io/Genealogy-Relationship-Name/coverage/> 2276: 2277: =item * L<Gedcom::Individual>, L<Genealogy::Relationship>, L<https://www.tfcg.ca/tableau-des-liens-de-parente>, 2278: 2279: =back 2280: 2281: =head1 AUTHOR 2282: 2283: Nigel Horne C<< <njh@nigelhorne.com> >> 2284: 2285: =head1 REPOSITORY 2286: 2287: L<https://github.com/nigelhorne/Genealogy-Relationship-Name> 2288: 2289: =head1 SUPPORT 2290: 2291: This module is provided as-is without any warranty. 2292: 2293: Please report any bugs or feature requests to C<bug-genealogy-relationship-name at rt.cpan.org>, 2294: or through the web interface at 2295: L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Genealogy-Relationship-Name>. 2296: I will be notified, and then you'll 2297: automatically be notified of progress on your bug as I make changes. 2298: 2299: You can find documentation for this module with the perldoc command. 2300: 2301: perldoc Genealogy::Relationship::Name 2302: 2303: You can also look for information at: 2304: 2305: =over 4 2306: 2307: =item * MetaCPAN 2308: 2309: L<https://metacpan.org/dist/Genealogy-Relationship-Name> 2310: 2311: =item * RT: CPAN's request tracker 2312: 2313: L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Genealogy-Relationship-Name> 2314: 2315: =item * CPAN Testers' Matrix 2316: 2317: L<http://matrix.cpantesters.org/?dist=Genealogy-Relationship-Name> 2318: 2319: =item * CPAN Testers Dependencies 2320: 2321: L<http://deps.cpantesters.org/?module=Genealogy::Relationship::Name> 2322: 2323: =back 2324: 2325: =head1 FORMAL SPECIFICATION 2326: 2327: =head2 new 2328: 2329: new ________________________________________________________ 2330: [In] class : String (class name or object) 2331: language : {en, es, fa, fr, de, la}? (optional default language 2332: logger : Log::Abstraction? (optional error logger) 2333: [Out] self : Genealogy::Relationship::Name 2334: 2335: Let params == get_params(args) 2336: Let params' == configure(class, params \ {logger}) 2337: union {logger -> params.logger} if logger in dom params 2338: self == bless(params', class) 2339: 2340: post: self.language == params.language if language in dom params 2341: self.logger == params.logger if logger in dom params 2342: ref(self) == 'Genealogy::Relationship::Name' 2343: 2344: =head2 name 2345: 2346: name ______________________________________________________ 2347: [In] steps_to_ancestor : N0 2348: steps_from_ancestor : N0 2349: sex : {M, F} 2350: language : {en, fr, de}? (default en) 2351: person : Object? 2352: [Out] result : String | undef 2353: 2354: Let key == steps_to_ancestor ++ "," ++ steps_from_ancestor 2355: Let table == RELATIONSHIP_TABLES(language)(sex) 2356: result == table(key) if key in dom table 2357: == undef otherwise 2358: 2359: =head2 supported_languages 2360: 2361: supported_languages ______________________________________ 2362: [In] (none) 2363: [Out] result : seq String 2364: 2365: result == sort(dom RELATIONSHIP_TABLES) 2366: 2367: =head2 known_sexes 2368: 2369: known_sexes ______________________________________________ 2370: [In] (none) 2371: [Out] result : seq String 2372: 2373: result == sort { $SEX_FEMALE, $SEX_MALE } 2374: 2375: =head1 LICENCE AND COPYRIGHT 2376: 2377: Copyright 2026 Nigel Horne. 2378: 2379: Usage is subject to the GPL2 licence terms. 2380: If you use it, 2381: please let me know. 2382: 2383: =cut