@treeviz/gedcom-parser 2.1.9 → 2.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/classes/common.d.ts.map +1 -1
  2. package/dist/classes/gedcom.d.ts +5 -0
  3. package/dist/classes/gedcom.d.ts.map +1 -1
  4. package/dist/classes/index.js +860 -464
  5. package/dist/classes/indi.d.ts.map +1 -1
  6. package/dist/classes/obje.d.ts.map +1 -1
  7. package/dist/cli/index.js +850 -454
  8. package/dist/constants/index.js +818 -448
  9. package/dist/factories/index.js +818 -448
  10. package/dist/index.js +865 -474
  11. package/dist/interfaces/indi.d.ts +1 -0
  12. package/dist/interfaces/indi.d.ts.map +1 -1
  13. package/dist/kinship-translator/index.js +818 -448
  14. package/dist/kinship-translator/kinship-translator.de.d.ts +2 -3
  15. package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
  16. package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
  17. package/dist/kinship-translator/kinship-translator.es.d.ts +2 -3
  18. package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
  19. package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -3
  20. package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
  21. package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
  22. package/dist/kinship-translator/kinship-translator.ja.d.ts.map +1 -1
  23. package/dist/kinship-translator/kinship-translator.ru.d.ts +1 -1
  24. package/dist/kinship-translator/kinship-translator.ru.d.ts.map +1 -1
  25. package/dist/kinship-translator/kinship-translator.zh.d.ts.map +1 -1
  26. package/dist/kinship-translator/patterns.de.d.ts +1 -0
  27. package/dist/kinship-translator/patterns.de.d.ts.map +1 -1
  28. package/dist/kinship-translator/patterns.es.d.ts +1 -0
  29. package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
  30. package/dist/kinship-translator/patterns.fr.d.ts +1 -0
  31. package/dist/kinship-translator/patterns.fr.d.ts.map +1 -1
  32. package/dist/kinship-translator/patterns.hu.d.ts.map +1 -1
  33. package/dist/kinship-translator/patterns.ru.d.ts +1 -0
  34. package/dist/kinship-translator/patterns.ru.d.ts.map +1 -1
  35. package/dist/kinship-translator/patterns.zh.d.ts.map +1 -1
  36. package/dist/utils/cache.d.ts.map +1 -1
  37. package/dist/utils/gedzip.d.ts.map +1 -1
  38. package/dist/utils/index.js +865 -474
  39. package/dist/utils/local-media.d.ts +7 -3
  40. package/dist/utils/local-media.d.ts.map +1 -1
  41. package/dist/utils/media-utils.d.ts +20 -0
  42. package/dist/utils/media-utils.d.ts.map +1 -1
  43. package/package.json +1 -1
@@ -107,6 +107,82 @@ var appendGedcomTrailer = (serialized) => {
107
107
  }
108
108
  return `${trimmed}${newline}0 TRLR`;
109
109
  };
110
+
111
+ // src/utils/media-utils.ts
112
+ var getFileExtension = (filename) => {
113
+ if (!filename) {
114
+ return "";
115
+ }
116
+ if (filename.startsWith("data:")) {
117
+ const mime = filename.slice(5).split(";")[0] || "";
118
+ const subtype = (mime.split("/")[1] || "").toLowerCase();
119
+ if (subtype === "jpeg") {
120
+ return "jpg";
121
+ }
122
+ return subtype.split("+")[0] || "";
123
+ }
124
+ const withoutQuery = filename.split(/[?#]/)[0] || filename;
125
+ const match = withoutQuery.match(/\.([^.]+)$/);
126
+ return match ? match[1].toLowerCase() : "";
127
+ };
128
+ var isImageFormat = (format2) => {
129
+ if (!format2) {
130
+ return false;
131
+ }
132
+ let normalized = format2.toLowerCase().trim();
133
+ if (normalized.startsWith("data:")) {
134
+ normalized = getFileExtension(normalized);
135
+ } else if (normalized.includes("/")) {
136
+ normalized = normalized.split("/")[1]?.split("+")[0] || "";
137
+ if (normalized === "jpeg") {
138
+ normalized = "jpg";
139
+ }
140
+ }
141
+ const imageFormats = [
142
+ "jpg",
143
+ "jpeg",
144
+ "png",
145
+ "gif",
146
+ "bmp",
147
+ "webp",
148
+ "svg",
149
+ "tiff",
150
+ "tif"
151
+ ];
152
+ return imageFormats.includes(normalized);
153
+ };
154
+ var resolveObjeForm = (obje) => {
155
+ const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
156
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
157
+ };
158
+ var mediaIdValue = (obje, path) => {
159
+ const value = obje?.get?.(path)?.toValue?.();
160
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
161
+ };
162
+ var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
163
+ var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
164
+ var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
165
+ var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
166
+ var ancestryMediaFileUrl = (namespace, imgId) => {
167
+ if (!namespace || !imgId) {
168
+ return void 0;
169
+ }
170
+ return `${ANCESTRY_MEDIA_RETRIEVAL_PREFIX}${ancestryMediaPath(namespace, imgId)}`;
171
+ };
172
+ var objeXrefKey = (obje, fallback = 0) => {
173
+ if (typeof obje?.id === "string" && obje.id) {
174
+ return obje.id;
175
+ }
176
+ const value = obje?.toValue?.();
177
+ if (typeof value === "string" && value.trim()) {
178
+ return value.trim();
179
+ }
180
+ if (typeof fallback === "string" && fallback.trim()) {
181
+ return fallback.trim();
182
+ }
183
+ return `@O${fallback}@`;
184
+ };
185
+ var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
110
186
  var List = class _List {
111
187
  // length = 0;
112
188
  constructor(items) {
@@ -756,7 +832,7 @@ var Common = class _Common {
756
832
  this,
757
833
  options.obje.namespace,
758
834
  options.obje.override,
759
- void 0,
835
+ this.isAncestry() ? ancestryMediaFileUrl : void 0,
760
836
  options.gedcomVersion
761
837
  );
762
838
  }
@@ -1652,7 +1728,7 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
1652
1728
  }
1653
1729
  return `${hungarianOrdinalize(
1654
1730
  degree
1655
- )}unokatestv\xE9r ${level}x elt\xE1vol\xEDtva`;
1731
+ )}unokatestv\xE9r ${Math.abs(level)}x elt\xE1vol\xEDtva`;
1656
1732
  }
1657
1733
  auncle() {
1658
1734
  const level = this.pathN?.level ?? 0;
@@ -1696,14 +1772,25 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
1696
1772
  return `${ordinalized ? `${ordinalized}unoka` : ""}testv\xE9r ${origPrefix.replace(/nagy$/, "")}unok\xE1ja`;
1697
1773
  }
1698
1774
  parent() {
1775
+ const level = Math.abs(this.pathN?.level ?? 0);
1776
+ if (level <= 1) {
1777
+ if (this.personN?.isMale()) {
1778
+ return "apa";
1779
+ }
1780
+ if (this.personN?.isFemale()) {
1781
+ return "anya";
1782
+ }
1783
+ return "sz\xFCl\u0151";
1784
+ }
1699
1785
  const prefix = this.directPrefix();
1786
+ const gen = prefix === "nagy" ? "" : prefix;
1700
1787
  if (this.personN?.isMale()) {
1701
- return `${prefix}apa`;
1788
+ return `${gen}nagyapa`;
1702
1789
  }
1703
1790
  if (this.personN?.isFemale()) {
1704
- return `${prefix}anya`;
1791
+ return `${gen}nagyanya`;
1705
1792
  }
1706
- return `${prefix}sz\xFCl\u0151`;
1793
+ return `${gen}nagysz\xFCl\u0151`;
1707
1794
  }
1708
1795
  child() {
1709
1796
  const level = Math.abs(this.pathN?.level ?? 0);
@@ -1897,27 +1984,30 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
1897
1984
  if (!degree) {
1898
1985
  return level < 0 ? this.nibling() : this.auncle();
1899
1986
  }
1900
- return `${ordinalize(degree)} cousin ${level}x removed`;
1987
+ return `${ordinalize(degree)} cousin ${Math.abs(level)}x removed`;
1901
1988
  }
1902
1989
  auncle() {
1903
- const prefix = this.directPrefix();
1990
+ const level = Math.abs(this.pathN?.level ?? 0);
1991
+ const greats = level <= 1 ? "" : "great-".repeat(level - 1);
1904
1992
  if (this.personN?.isMale()) {
1905
- return `${prefix}uncle`;
1993
+ return `${greats}uncle`;
1906
1994
  }
1907
1995
  if (this.personN?.isFemale()) {
1908
- return `${prefix}aunt`;
1996
+ return `${greats}aunt`;
1909
1997
  }
1910
- return `${prefix}auncle`;
1998
+ return greats ? `${greats}uncle/${greats}aunt` : "uncle/aunt";
1911
1999
  }
1912
2000
  nibling() {
1913
- const prefix = this.directPrefix();
2001
+ const level = Math.abs(this.pathN?.level ?? 0);
2002
+ const greats = level <= 2 ? "" : "great-".repeat(level - 2);
2003
+ const grand = level <= 1 ? "" : "grand";
1914
2004
  if (this.personN?.isMale()) {
1915
- return `${prefix}nephew`;
2005
+ return `${greats}${grand}nephew`;
1916
2006
  }
1917
2007
  if (this.personN?.isFemale()) {
1918
- return `${prefix}niece`;
2008
+ return `${greats}${grand}niece`;
1919
2009
  }
1920
- return `${prefix}nibling`;
2010
+ return greats || grand ? `${greats}${grand}nephew/${greats}${grand}niece` : "nephew/niece";
1921
2011
  }
1922
2012
  parent() {
1923
2013
  const prefix = this.directPrefix();
@@ -2045,45 +2135,64 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
2045
2135
  };
2046
2136
 
2047
2137
  // src/kinship-translator/patterns.de.ts
2138
+ var parentRelationsDe = {
2139
+ step: "Stief",
2140
+ foster: "Pflege",
2141
+ adopted: "Adoptiv"
2142
+ };
2048
2143
  var InLawsDe = {
2049
- "Ehepartner von (kind|tochter|sohn)": "Schwiegerkind",
2050
- "Ehefrau von (kind|tochter|sohn)": "Schwiegertochter",
2051
- "Ehemann von (kind|tochter|sohn)": "Schwiegersohn",
2052
- "mutter des (Ehepartner|Ehefrau|Ehemann)s": "Schwiegermutter",
2053
- "vater des (Ehepartner|Ehefrau|Ehemann)s": "Schwiegervater",
2054
- "elternteil des (Ehepartner|Ehefrau|Ehemann)s": "Schwiegerelternteil",
2055
- "Ehefrau von (Halb)?(geschwister|schwester|bruder)": "Schw\xE4gerin",
2056
- "Ehemann von (Halb)?(geschwister|schwester|bruder)": "Schwager",
2057
- "Ehepartner von (Halb)?(geschwister|schwester|bruder)": "Schwager/Schw\xE4gerin",
2058
- "(Halb)?schwester des (Ehepartner|Ehefrau|Ehemann)s": "Schw\xE4gerin",
2059
- "(Halb)?bruder des (Ehepartner|Ehefrau|Ehemann)s": "Schwager",
2060
- "(Halb)?geschwister des (Ehepartner|Ehefrau|Ehemann)s": "Schwager/Schw\xE4gerin"
2144
+ "Ehepartner von (Kind|Tochter|Sohn)": "Schwiegerkind",
2145
+ "Ehefrau von (Kind|Tochter|Sohn)": "Schwiegertochter",
2146
+ "Ehemann von (Kind|Tochter|Sohn)": "Schwiegersohn",
2147
+ "Mutter (des Ehepartners|des Ehemanns|der Ehefrau)": "Schwiegermutter",
2148
+ "Vater (des Ehepartners|des Ehemanns|der Ehefrau)": "Schwiegervater",
2149
+ "Elternteil (des Ehepartners|des Ehemanns|der Ehefrau)": "Schwiegerelternteil",
2150
+ "Ehefrau von (Halb)?-?(Geschwister|Schwester|Bruder)": "Schw\xE4gerin",
2151
+ "Ehemann von (Halb)?-?(Geschwister|Schwester|Bruder)": "Schwager",
2152
+ "Ehepartner von (Halb)?-?(Geschwister|Schwester|Bruder)": "Schwager/Schw\xE4gerin",
2153
+ "(Halb)?-?(Schwester|schwester) (des Ehepartners|des Ehemanns|der Ehefrau)": "Schw\xE4gerin",
2154
+ "(Halb)?-?(Bruder|bruder) (des Ehepartners|des Ehemanns|der Ehefrau)": "Schwager",
2155
+ "(Halb)?-?(Geschwister|geschwister) (des Ehepartners|des Ehemanns|der Ehefrau)": "Schwager/Schw\xE4gerin"
2061
2156
  };
2062
2157
 
2063
2158
  // src/kinship-translator/kinship-translator.de.ts
2064
- var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2065
- directPrefix() {
2066
- const level = Math.abs(this.pathN?.level ?? 0);
2067
- if (level <= 1) {
2068
- return "";
2069
- }
2070
- if (level === 2) {
2071
- return "Gro\xDF";
2072
- }
2073
- if (level === 3) {
2074
- return "Urgro\xDF";
2075
- }
2076
- return `Ur${level - 2}-gro\xDF`;
2159
+ var sexOf = (person) => {
2160
+ if (person?.isMale?.()) {
2161
+ return "m";
2077
2162
  }
2163
+ if (person?.isFemale?.()) {
2164
+ return "f";
2165
+ }
2166
+ return "n";
2167
+ };
2168
+ var pick = (sex, male, female, neutral) => {
2169
+ if (sex === "m") {
2170
+ return male;
2171
+ }
2172
+ if (sex === "f") {
2173
+ return female;
2174
+ }
2175
+ return neutral;
2176
+ };
2177
+ var ur = (count) => count > 0 ? "Ur".repeat(count) : "";
2178
+ var genitiveArticle = (spouseType) => {
2179
+ if (spouseType === "Ehefrau") {
2180
+ return `der ${spouseType}`;
2181
+ }
2182
+ return `des ${spouseType}s`;
2183
+ };
2184
+ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2078
2185
  indirect() {
2079
2186
  let degree = Math.abs(this.pathN?.degree ?? 0);
2080
2187
  if (degree > 0) {
2081
2188
  degree = degree - 1;
2082
2189
  }
2083
- if (degree === 1) {
2084
- return `Cousin`;
2190
+ const sex = sexOf(this.personN);
2191
+ const cousin = pick(sex, "Cousin", "Cousine", "Cousin/Cousine");
2192
+ if (degree <= 1) {
2193
+ return cousin;
2085
2194
  }
2086
- return `Cousin ${degree}. Grades`;
2195
+ return `${cousin} ${degree}. Grades`;
2087
2196
  }
2088
2197
  removal() {
2089
2198
  const level = this.pathN?.level ?? 0;
@@ -2094,101 +2203,101 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2094
2203
  if (!degree) {
2095
2204
  return level < 0 ? this.nibling() : this.auncle();
2096
2205
  }
2097
- return `Cousin ${degree}. Grades ${Math.abs(level)}\xD7 entfernt`;
2206
+ return `${this.indirect()} ${Math.abs(level)}\xD7 entfernt`;
2098
2207
  }
2099
2208
  auncle() {
2100
- const prefix = this.directPrefix();
2101
- if (this.personN?.isMale()) {
2102
- return `${prefix}onkel`;
2103
- }
2104
- if (this.personN?.isFemale()) {
2105
- return `${prefix}tante`;
2209
+ const level = Math.abs(this.pathN?.level ?? 0);
2210
+ const sex = sexOf(this.personN);
2211
+ if (level <= 1) {
2212
+ return pick(sex, "Onkel", "Tante", "Onkel/Tante");
2106
2213
  }
2107
- return `${prefix}onkel/tante`;
2214
+ const prefix = `${ur(level - 2)}Gro\xDF`;
2215
+ return pick(
2216
+ sex,
2217
+ `${prefix}onkel`,
2218
+ `${prefix}tante`,
2219
+ `${prefix}onkel/tante`
2220
+ );
2108
2221
  }
2109
2222
  nibling() {
2110
- const prefix = this.directPrefix();
2111
- if (this.personN?.isMale()) {
2112
- return `${prefix}neffe`;
2113
- }
2114
- if (this.personN?.isFemale()) {
2115
- return `${prefix}nichte`;
2223
+ const level = Math.abs(this.pathN?.level ?? 0);
2224
+ const sex = sexOf(this.personN);
2225
+ if (level <= 1) {
2226
+ return pick(sex, "Neffe", "Nichte", "Neffe/Nichte");
2116
2227
  }
2117
- return `${prefix}neffe/nichte`;
2228
+ const prefix = `${ur(level - 2)}Gro\xDF`;
2229
+ return pick(
2230
+ sex,
2231
+ `${prefix}neffe`,
2232
+ `${prefix}nichte`,
2233
+ `${prefix}neffe/nichte`
2234
+ );
2118
2235
  }
2119
2236
  parent() {
2120
- const prefix = this.directPrefix();
2121
- if (this.personN?.isMale()) {
2122
- return `${prefix}vater`;
2123
- }
2124
- if (this.personN?.isFemale()) {
2125
- return `${prefix}mutter`;
2237
+ const level = Math.abs(this.pathN?.level ?? 0);
2238
+ const sex = sexOf(this.personN);
2239
+ if (level <= 1) {
2240
+ return pick(sex, "Vater", "Mutter", "Elternteil");
2126
2241
  }
2127
- return `${prefix}elternteil`;
2242
+ const prefix = `${ur(level - 2)}Gro\xDF`;
2243
+ return pick(
2244
+ sex,
2245
+ `${prefix}vater`,
2246
+ `${prefix}mutter`,
2247
+ `${prefix}elternteil`
2248
+ );
2128
2249
  }
2129
2250
  child() {
2130
- const prefix = this.directPrefix();
2131
- if (this.personN?.isMale()) {
2132
- return `${prefix}sohn`;
2133
- }
2134
- if (this.personN?.isFemale()) {
2135
- return `${prefix}tochter`;
2251
+ const level = Math.abs(this.pathN?.level ?? 0);
2252
+ const sex = sexOf(this.personN);
2253
+ if (level <= 1) {
2254
+ return pick(sex, "Sohn", "Tochter", "Kind");
2136
2255
  }
2137
- return `${prefix}kind`;
2256
+ const prefix = ur(level - 2);
2257
+ return pick(
2258
+ sex,
2259
+ `${prefix}Enkel`,
2260
+ `${prefix}Enkelin`,
2261
+ `${prefix}Enkelkind`
2262
+ );
2138
2263
  }
2139
2264
  sibling() {
2140
- if (this.personN?.isMale()) {
2141
- return "bruder";
2142
- }
2143
- if (this.personN?.isFemale()) {
2144
- return "schwester";
2145
- }
2146
- return "geschwister";
2265
+ return pick(sexOf(this.personN), "Bruder", "Schwester", "Geschwister");
2147
2266
  }
2148
2267
  halfBlood(relation) {
2149
2268
  if (!relation || !this.isHalfBlood) {
2150
2269
  return relation ?? "";
2151
2270
  }
2152
- if (/^[A-ZÄÖÜ]/.test(relation) || /[-\s]/.test(relation)) {
2271
+ if (/[\s-]/.test(relation) || /^(Groß|Ur)/.test(relation)) {
2153
2272
  return `Halb-${relation}`;
2154
2273
  }
2155
- return `Halb${relation}`;
2274
+ return `Halb${relation.charAt(0).toLowerCase()}${relation.slice(1)}`;
2156
2275
  }
2157
2276
  spouse() {
2158
- if (this.personN?.isMale()) {
2159
- return "Ehemann";
2160
- }
2161
- if (this.personN?.isFemale()) {
2162
- return "Ehefrau";
2163
- }
2164
- return "Ehepartner";
2277
+ return pick(sexOf(this.personN), "Ehemann", "Ehefrau", "Ehepartner");
2165
2278
  }
2166
2279
  ofSpouse(relation) {
2167
2280
  if (!relation) {
2168
2281
  return "";
2169
2282
  }
2170
- const spouse = this.path?.[1].indi;
2171
- let spouseType = "Ehepartner";
2172
- if (spouse?.isMale()) {
2173
- spouseType = "Ehemann";
2174
- }
2175
- if (spouse?.isFemale()) {
2176
- spouseType = "Ehefrau";
2177
- }
2178
- return `${relation} des ${spouseType}s`;
2283
+ const spouseType = pick(
2284
+ sexOf(this.path?.[1].indi),
2285
+ "Ehemann",
2286
+ "Ehefrau",
2287
+ "Ehepartner"
2288
+ );
2289
+ return `${relation} ${genitiveArticle(spouseType)}`;
2179
2290
  }
2180
2291
  spouseOf(relation) {
2181
2292
  if (!relation) {
2182
2293
  return "";
2183
2294
  }
2184
- const spouse = this.path?.[this.path.length - 1].indi;
2185
- let spouseType = "Ehepartner";
2186
- if (spouse?.isMale()) {
2187
- spouseType = "Ehemann";
2188
- }
2189
- if (spouse?.isFemale()) {
2190
- spouseType = "Ehefrau";
2191
- }
2295
+ const spouseType = pick(
2296
+ sexOf(this.path?.[this.path.length - 1].indi),
2297
+ "Ehemann",
2298
+ "Ehefrau",
2299
+ "Ehepartner"
2300
+ );
2192
2301
  return `${spouseType} von ${relation}`;
2193
2302
  }
2194
2303
  of(relation) {
@@ -2206,8 +2315,8 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2206
2315
  if (!name || !relation) {
2207
2316
  return relation ?? "";
2208
2317
  }
2209
- if (relation.includes(" des ") || relation.includes(" von ")) {
2210
- return relation.replace(/ (des|von) /, ` $1 ${name}s `);
2318
+ if (relation.includes(" des ") || relation.includes(" der ") || relation.includes(" von ")) {
2319
+ return relation.replace(/ (des|der|von) /, ` $1 ${name}s `);
2211
2320
  }
2212
2321
  return `${name}s ${relation}`;
2213
2322
  }
@@ -2237,50 +2346,82 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2237
2346
  if (!relation || !this.pathN?.relation) {
2238
2347
  return relation ?? "";
2239
2348
  }
2240
- return `${this.pathN.relation} ${relation}`;
2349
+ const prefix = parentRelationsDe[this.pathN.relation];
2350
+ if (!prefix) {
2351
+ return relation;
2352
+ }
2353
+ if (prefix.endsWith("-") || prefix.endsWith(" ")) {
2354
+ return `${prefix}${relation}`;
2355
+ }
2356
+ return `${prefix}${relation.charAt(0).toLowerCase()}${relation.slice(1)}`;
2241
2357
  }
2242
2358
  };
2243
2359
 
2244
2360
  // src/kinship-translator/patterns.fr.ts
2361
+ var parentRelationsFr = {
2362
+ step: "step",
2363
+ foster: "foster",
2364
+ adopted: "adopted"
2365
+ };
2245
2366
  var InLawsFr = {
2246
2367
  "conjoint de (enfant|fille|fils)": "beau-fils/belle-fille",
2247
2368
  "\xE9pouse de (enfant|fille|fils)": "belle-fille",
2248
2369
  "mari de (enfant|fille|fils)": "gendre",
2249
- "m\xE8re du (conjoint|\xE9pouse|mari)": "belle-m\xE8re",
2250
- "p\xE8re du (conjoint|\xE9pouse|mari)": "beau-p\xE8re",
2251
- "parent du (conjoint|\xE9pouse|mari)": "beau-parent",
2370
+ "m\xE8re (du mari|du conjoint|de l'\xE9pouse)": "belle-m\xE8re",
2371
+ "p\xE8re (du mari|du conjoint|de l'\xE9pouse)": "beau-p\xE8re",
2372
+ "parent (du mari|du conjoint|de l'\xE9pouse)": "beau-parent",
2252
2373
  "\xE9pouse de (demi-)?(fr\xE8re/s\u0153ur|s\u0153ur|fr\xE8re)": "belle-s\u0153ur",
2253
2374
  "mari de (demi-)?(fr\xE8re/s\u0153ur|s\u0153ur|fr\xE8re)": "beau-fr\xE8re",
2254
2375
  "conjoint de (demi-)?(fr\xE8re/s\u0153ur|s\u0153ur|fr\xE8re)": "beau-fr\xE8re/belle-s\u0153ur",
2255
- "(demi-)?s\u0153ur du (conjoint|\xE9pouse|mari)": "belle-s\u0153ur",
2256
- "(demi-)?fr\xE8re du (conjoint|\xE9pouse|mari)": "beau-fr\xE8re",
2257
- "(demi-)?fr\xE8re/s\u0153ur du (conjoint|\xE9pouse|mari)": "beau-fr\xE8re/belle-s\u0153ur"
2376
+ "(demi-)?s\u0153ur (du mari|du conjoint|de l'\xE9pouse)": "belle-s\u0153ur",
2377
+ "(demi-)?fr\xE8re (du mari|du conjoint|de l'\xE9pouse)": "beau-fr\xE8re",
2378
+ "(demi-)?fr\xE8re/s\u0153ur (du mari|du conjoint|de l'\xE9pouse)": "beau-fr\xE8re/belle-s\u0153ur"
2258
2379
  };
2259
2380
 
2260
2381
  // src/kinship-translator/kinship-translator.fr.ts
2261
- var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2262
- directPrefix() {
2263
- const level = Math.abs(this.pathN?.level ?? 0);
2264
- if (level <= 1) {
2265
- return "";
2266
- }
2267
- if (level === 2) {
2268
- return "grand-";
2269
- }
2270
- if (level === 3) {
2271
- return "arri\xE8re-grand-";
2272
- }
2273
- return `arri\xE8re${level - 2}-grand-`;
2382
+ var sexOf2 = (person) => {
2383
+ if (person?.isMale?.()) {
2384
+ return "m";
2385
+ }
2386
+ if (person?.isFemale?.()) {
2387
+ return "f";
2274
2388
  }
2389
+ return "n";
2390
+ };
2391
+ var pick2 = (sex, male, female, neutral) => {
2392
+ if (sex === "m") {
2393
+ return male;
2394
+ }
2395
+ if (sex === "f") {
2396
+ return female;
2397
+ }
2398
+ return neutral;
2399
+ };
2400
+ var arriere = (count) => count > 0 ? "arri\xE8re-".repeat(count) : "";
2401
+ var frenchOrdinal = (n) => n === 1 ? "1er" : `${n}e`;
2402
+ var isFeminineRelation = (relation) => /mère|fille|sœur|tante|nièce|cousine|épouse/.test(relation);
2403
+ var ofSpousePrep = (spouseType) => {
2404
+ if (spouseType === "\xE9pouse") {
2405
+ return "de l'";
2406
+ }
2407
+ return "du ";
2408
+ };
2409
+ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2275
2410
  indirect() {
2276
2411
  let degree = Math.abs(this.pathN?.degree ?? 0);
2277
2412
  if (degree > 0) {
2278
2413
  degree = degree - 1;
2279
2414
  }
2280
- if (degree === 1) {
2281
- return `cousin`;
2415
+ const cousin = pick2(
2416
+ sexOf2(this.personN),
2417
+ "cousin",
2418
+ "cousine",
2419
+ "cousin/cousine"
2420
+ );
2421
+ if (degree <= 1) {
2422
+ return cousin;
2282
2423
  }
2283
- return `cousin au ${ordinalize(degree)} degr\xE9`;
2424
+ return `${cousin} au ${frenchOrdinal(degree)} degr\xE9`;
2284
2425
  }
2285
2426
  removal() {
2286
2427
  const level = this.pathN?.level ?? 0;
@@ -2291,56 +2432,57 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2291
2432
  if (!degree) {
2292
2433
  return level < 0 ? this.nibling() : this.auncle();
2293
2434
  }
2294
- return `cousin au ${ordinalize(degree)} degr\xE9 ${Math.abs(level)}\xD7 \xE9loign\xE9`;
2435
+ return `${this.indirect()} ${Math.abs(level)}\xD7 \xE9loign\xE9`;
2295
2436
  }
2296
2437
  auncle() {
2297
- const prefix = this.directPrefix();
2298
- if (this.personN?.isMale()) {
2299
- return `${prefix}oncle`;
2300
- }
2301
- if (this.personN?.isFemale()) {
2302
- return `${prefix}tante`;
2438
+ const level = Math.abs(this.pathN?.level ?? 0);
2439
+ const sex = sexOf2(this.personN);
2440
+ const base = pick2(sex, "oncle", "tante", "oncle/tante");
2441
+ if (level <= 1) {
2442
+ return base;
2303
2443
  }
2304
- return `${prefix}oncle/tante`;
2444
+ const grands = pick2(
2445
+ sex,
2446
+ "grand-oncle",
2447
+ "grand-tante",
2448
+ "grand-oncle/tante"
2449
+ );
2450
+ return `${arriere(level - 2)}${grands}`;
2305
2451
  }
2306
2452
  nibling() {
2307
- const prefix = this.directPrefix();
2308
- if (this.personN?.isMale()) {
2309
- return `${prefix}neveu`;
2310
- }
2311
- if (this.personN?.isFemale()) {
2312
- return `${prefix}ni\xE8ce`;
2453
+ const level = Math.abs(this.pathN?.level ?? 0);
2454
+ const sex = sexOf2(this.personN);
2455
+ if (level <= 1) {
2456
+ return pick2(sex, "neveu", "ni\xE8ce", "neveu/ni\xE8ce");
2313
2457
  }
2314
- return `${prefix}neveu/ni\xE8ce`;
2458
+ const grands = pick2(
2459
+ sex,
2460
+ "grand-neveu",
2461
+ "grande-ni\xE8ce",
2462
+ "grand-neveu/grande-ni\xE8ce"
2463
+ );
2464
+ return `${arriere(level - 2)}${grands}`;
2315
2465
  }
2316
2466
  parent() {
2317
- const prefix = this.directPrefix();
2318
- if (this.personN?.isMale()) {
2319
- return `${prefix}p\xE8re`;
2320
- }
2321
- if (this.personN?.isFemale()) {
2322
- return `${prefix}m\xE8re`;
2467
+ const level = Math.abs(this.pathN?.level ?? 0);
2468
+ const sex = sexOf2(this.personN);
2469
+ if (level <= 1) {
2470
+ return pick2(sex, "p\xE8re", "m\xE8re", "parent");
2323
2471
  }
2324
- return `${prefix}parent`;
2472
+ const grands = pick2(sex, "grand-p\xE8re", "grand-m\xE8re", "grand-parent");
2473
+ return `${arriere(level - 2)}${grands}`;
2325
2474
  }
2326
2475
  child() {
2327
- const prefix = this.directPrefix();
2328
- if (this.personN?.isMale()) {
2329
- return `${prefix}fils`;
2330
- }
2331
- if (this.personN?.isFemale()) {
2332
- return `${prefix}fille`;
2476
+ const level = Math.abs(this.pathN?.level ?? 0);
2477
+ const sex = sexOf2(this.personN);
2478
+ if (level <= 1) {
2479
+ return pick2(sex, "fils", "fille", "enfant");
2333
2480
  }
2334
- return `${prefix}enfant`;
2481
+ const petits = pick2(sex, "petit-fils", "petite-fille", "petit-enfant");
2482
+ return `${arriere(level - 2)}${petits}`;
2335
2483
  }
2336
2484
  sibling() {
2337
- if (this.personN?.isMale()) {
2338
- return "fr\xE8re";
2339
- }
2340
- if (this.personN?.isFemale()) {
2341
- return "s\u0153ur";
2342
- }
2343
- return "fr\xE8re/s\u0153ur";
2485
+ return pick2(sexOf2(this.personN), "fr\xE8re", "s\u0153ur", "fr\xE8re/s\u0153ur");
2344
2486
  }
2345
2487
  halfBlood(relation) {
2346
2488
  if (!relation || !this.isHalfBlood) {
@@ -2349,40 +2491,30 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2349
2491
  return `demi-${relation}`;
2350
2492
  }
2351
2493
  spouse() {
2352
- if (this.personN?.isMale()) {
2353
- return "mari";
2354
- }
2355
- if (this.personN?.isFemale()) {
2356
- return "\xE9pouse";
2357
- }
2358
- return "conjoint";
2494
+ return pick2(sexOf2(this.personN), "mari", "\xE9pouse", "conjoint");
2359
2495
  }
2360
2496
  ofSpouse(relation) {
2361
2497
  if (!relation) {
2362
2498
  return "";
2363
2499
  }
2364
- const spouse = this.path?.[1].indi;
2365
- let spouseType = "conjoint";
2366
- if (spouse?.isMale()) {
2367
- spouseType = "mari";
2368
- }
2369
- if (spouse?.isFemale()) {
2370
- spouseType = "\xE9pouse";
2371
- }
2372
- return `${relation} du ${spouseType}`;
2500
+ const spouseType = pick2(
2501
+ sexOf2(this.path?.[1].indi),
2502
+ "mari",
2503
+ "\xE9pouse",
2504
+ "conjoint"
2505
+ );
2506
+ return `${relation} ${ofSpousePrep(spouseType)}${spouseType}`;
2373
2507
  }
2374
2508
  spouseOf(relation) {
2375
2509
  if (!relation) {
2376
2510
  return "";
2377
2511
  }
2378
- const spouse = this.path?.[this.path.length - 1].indi;
2379
- let spouseType = "conjoint";
2380
- if (spouse?.isMale()) {
2381
- spouseType = "mari";
2382
- }
2383
- if (spouse?.isFemale()) {
2384
- spouseType = "\xE9pouse";
2385
- }
2512
+ const spouseType = pick2(
2513
+ sexOf2(this.path?.[this.path.length - 1].indi),
2514
+ "mari",
2515
+ "\xE9pouse",
2516
+ "conjoint"
2517
+ );
2386
2518
  return `${spouseType} de ${relation}`;
2387
2519
  }
2388
2520
  of(relation) {
@@ -2403,6 +2535,9 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2403
2535
  if (relation.includes(" du ") || relation.includes(" de ")) {
2404
2536
  return relation.replace(/ (du|de) /, ` $1 ${name} `);
2405
2537
  }
2538
+ if (relation.includes(" de l'")) {
2539
+ return relation.replace(" de l'", ` de ${name} l'`);
2540
+ }
2406
2541
  return `${relation} de ${name}`;
2407
2542
  }
2408
2543
  inLaw(relation) {
@@ -2431,50 +2566,118 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2431
2566
  if (!relation || !this.pathN?.relation) {
2432
2567
  return relation ?? "";
2433
2568
  }
2434
- return `${this.pathN.relation} ${relation}`;
2569
+ const kind = parentRelationsFr[this.pathN.relation];
2570
+ if (!kind) {
2571
+ return relation;
2572
+ }
2573
+ if (kind === "step") {
2574
+ return `${isFeminineRelation(relation) ? "belle-" : "beau-"}${relation}`;
2575
+ }
2576
+ if (kind === "adopted") {
2577
+ return `${relation} ${isFeminineRelation(relation) ? "adoptive" : "adoptif"}`;
2578
+ }
2579
+ if (kind === "foster") {
2580
+ return `${relation} d'accueil`;
2581
+ }
2582
+ return relation;
2583
+ }
2584
+ };
2585
+
2586
+ // src/kinship-translator/patterns.es.ts
2587
+ var parentRelationsEs = {
2588
+ step: {
2589
+ padre: "padrastro",
2590
+ madre: "madrastra",
2591
+ hijo: "hijastro",
2592
+ hija: "hijastra",
2593
+ hermano: "hermanastro",
2594
+ hermana: "hermanastra",
2595
+ abuelo: "abuelastro",
2596
+ abuela: "abuelastra"
2597
+ }
2598
+ };
2599
+ var InLawsEs = {
2600
+ "c\xF3nyuge de (hijo/hija|hija|hijo)": "yerno/nuera",
2601
+ "esposa de (hijo/hija|hija|hijo)": "nuera",
2602
+ "esposo de (hijo/hija|hija|hijo)": "yerno",
2603
+ "madre (del c\xF3nyuge|del esposo|de la esposa)": "suegra",
2604
+ "padre (del c\xF3nyuge|del esposo|de la esposa)": "suegro",
2605
+ "padre/madre (del c\xF3nyuge|del esposo|de la esposa)": "suegro/suegra",
2606
+ "esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
2607
+ "esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
2608
+ "c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
2609
+ "(medio |media |medio/a )?hermana (del c\xF3nyuge|del esposo|de la esposa)": "cu\xF1ada",
2610
+ "(medio |media |medio/a )?hermano (del c\xF3nyuge|del esposo|de la esposa)": "cu\xF1ado",
2611
+ "(medio |media |medio/a )?hermano/hermana (del c\xF3nyuge|del esposo|de la esposa)": "cu\xF1ado/cu\xF1ada"
2612
+ };
2613
+
2614
+ // src/kinship-translator/kinship-translator.es.ts
2615
+ var sexOf3 = (person) => {
2616
+ if (person?.isMale?.()) {
2617
+ return "m";
2618
+ }
2619
+ if (person?.isFemale?.()) {
2620
+ return "f";
2621
+ }
2622
+ return "n";
2623
+ };
2624
+ var pick3 = (sex, male, female, neutral) => {
2625
+ if (sex === "m") {
2626
+ return male;
2627
+ }
2628
+ if (sex === "f") {
2629
+ return female;
2435
2630
  }
2631
+ return neutral;
2436
2632
  };
2437
-
2438
- // src/kinship-translator/patterns.es.ts
2439
- var InLawsEs = {
2440
- "c\xF3nyuge de (hijo/hija|hija|hijo)": "yerno/nuera",
2441
- "esposa de (hijo/hija|hija|hijo)": "nuera",
2442
- "esposo de (hijo/hija|hija|hijo)": "yerno",
2443
- "madre del (c\xF3nyuge|esposa|esposo)": "suegra",
2444
- "padre del (c\xF3nyuge|esposa|esposo)": "suegro",
2445
- "padre/madre del (c\xF3nyuge|esposa|esposo)": "suegro/suegra",
2446
- "esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
2447
- "esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
2448
- "c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
2449
- "(medio |media |medio/a )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
2450
- "(medio |media |medio/a )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
2451
- "(medio |media |medio/a )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
2633
+ var SPANISH_ORDINALS_M = [
2634
+ "",
2635
+ "",
2636
+ "segundo",
2637
+ "tercero",
2638
+ "cuarto",
2639
+ "quinto",
2640
+ "sexto",
2641
+ "s\xE9ptimo",
2642
+ "octavo",
2643
+ "noveno",
2644
+ "d\xE9cimo"
2645
+ ];
2646
+ var SPANISH_ORDINALS_F = [
2647
+ "",
2648
+ "",
2649
+ "segunda",
2650
+ "tercera",
2651
+ "cuarta",
2652
+ "quinta",
2653
+ "sexta",
2654
+ "s\xE9ptima",
2655
+ "octava",
2656
+ "novena",
2657
+ "d\xE9cima"
2658
+ ];
2659
+ var spanishOrdinal = (n, sex) => {
2660
+ const list = sex === "f" ? SPANISH_ORDINALS_F : SPANISH_ORDINALS_M;
2661
+ return list[n] ?? `${n}.\xBA`;
2452
2662
  };
2453
-
2454
- // src/kinship-translator/kinship-translator.es.ts
2455
- var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2456
- directPrefix() {
2457
- const level = Math.abs(this.pathN?.level ?? 0);
2458
- if (level <= 1) {
2459
- return "";
2460
- }
2461
- if (level === 2) {
2462
- return "bisabuel";
2463
- }
2464
- if (level === 3) {
2465
- return "tatarabuel";
2466
- }
2467
- return `t\xE1tara${level - 2}-abuel`;
2663
+ var ofSpousePrep2 = (spouseType) => {
2664
+ if (spouseType === "esposa") {
2665
+ return "de la ";
2468
2666
  }
2667
+ return "del ";
2668
+ };
2669
+ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2469
2670
  indirect() {
2470
2671
  let degree = Math.abs(this.pathN?.degree ?? 0);
2471
2672
  if (degree > 0) {
2472
2673
  degree = degree - 1;
2473
2674
  }
2474
- if (degree === 1) {
2475
- return `primo`;
2675
+ const sex = sexOf3(this.personN);
2676
+ const cousin = pick3(sex, "primo", "prima", "primo/prima");
2677
+ if (degree <= 1) {
2678
+ return cousin;
2476
2679
  }
2477
- return `primo ${ordinalize(degree)}`;
2680
+ return `${cousin} ${spanishOrdinal(degree, sex)}`;
2478
2681
  }
2479
2682
  removal() {
2480
2683
  const level = this.pathN?.level ?? 0;
@@ -2485,56 +2688,133 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2485
2688
  if (!degree) {
2486
2689
  return level < 0 ? this.nibling() : this.auncle();
2487
2690
  }
2488
- return `primo ${ordinalize(degree)} ${Math.abs(level)}\xD7 separado`;
2691
+ return `${this.indirect()} ${Math.abs(level)}\xD7 separado`;
2489
2692
  }
2490
2693
  auncle() {
2491
- const prefix = this.directPrefix();
2492
- if (this.personN?.isMale()) {
2493
- return `${prefix}t\xEDo`;
2694
+ const level = Math.abs(this.pathN?.level ?? 0);
2695
+ const sex = sexOf3(this.personN);
2696
+ if (level <= 1) {
2697
+ return pick3(sex, "t\xEDo", "t\xEDa", "t\xEDo/t\xEDa");
2494
2698
  }
2495
- if (this.personN?.isFemale()) {
2496
- return `${prefix}t\xEDa`;
2699
+ if (level === 2) {
2700
+ return pick3(sex, "t\xEDo abuelo", "t\xEDa abuela", "t\xEDo/t\xEDa abuelo");
2701
+ }
2702
+ if (level === 3) {
2703
+ return pick3(
2704
+ sex,
2705
+ "t\xEDo bisabuelo",
2706
+ "t\xEDa bisabuela",
2707
+ "t\xEDo/t\xEDa bisabuelo"
2708
+ );
2497
2709
  }
2498
- return `${prefix}t\xEDo/t\xEDa`;
2710
+ return pick3(
2711
+ sex,
2712
+ `t\xEDo abuelo (${level - 1}.\xBA)`,
2713
+ `t\xEDa abuela (${level - 1}.\xAA)`,
2714
+ `t\xEDo/t\xEDa abuelo (${level - 1}.\xBA)`
2715
+ );
2499
2716
  }
2500
2717
  nibling() {
2501
- const prefix = this.directPrefix();
2502
- if (this.personN?.isMale()) {
2503
- return `${prefix}sobrino`;
2718
+ const level = Math.abs(this.pathN?.level ?? 0);
2719
+ const sex = sexOf3(this.personN);
2720
+ if (level <= 1) {
2721
+ return pick3(sex, "sobrino", "sobrina", "sobrino/sobrina");
2504
2722
  }
2505
- if (this.personN?.isFemale()) {
2506
- return `${prefix}sobrina`;
2723
+ if (level === 2) {
2724
+ return pick3(
2725
+ sex,
2726
+ "sobrino nieto",
2727
+ "sobrina nieta",
2728
+ "sobrino/sobrina nieto"
2729
+ );
2730
+ }
2731
+ if (level === 3) {
2732
+ return pick3(
2733
+ sex,
2734
+ "sobrino bisnieto",
2735
+ "sobrina bisnieta",
2736
+ "sobrino/sobrina bisnieto"
2737
+ );
2507
2738
  }
2508
- return `${prefix}sobrino/sobrina`;
2739
+ return pick3(
2740
+ sex,
2741
+ `sobrino nieto (${level - 1}.\xBA)`,
2742
+ `sobrina nieta (${level - 1}.\xAA)`,
2743
+ `sobrino/sobrina nieto (${level - 1}.\xBA)`
2744
+ );
2509
2745
  }
2510
2746
  parent() {
2511
- const prefix = this.directPrefix();
2512
- if (this.personN?.isMale()) {
2513
- return `${prefix}padre`;
2747
+ const level = Math.abs(this.pathN?.level ?? 0);
2748
+ const sex = sexOf3(this.personN);
2749
+ if (level <= 1) {
2750
+ return pick3(sex, "padre", "madre", "padre/madre");
2514
2751
  }
2515
- if (this.personN?.isFemale()) {
2516
- return `${prefix}madre`;
2752
+ if (level === 2) {
2753
+ return pick3(sex, "abuelo", "abuela", "abuelo/abuela");
2754
+ }
2755
+ if (level === 3) {
2756
+ return pick3(sex, "bisabuelo", "bisabuela", "bisabuelo/bisabuela");
2517
2757
  }
2518
- return `${prefix}padre/madre`;
2758
+ if (level === 4) {
2759
+ return pick3(
2760
+ sex,
2761
+ "tatarabuelo",
2762
+ "tatarabuela",
2763
+ "tatarabuelo/tatarabuela"
2764
+ );
2765
+ }
2766
+ if (level === 5) {
2767
+ return pick3(
2768
+ sex,
2769
+ "trastatarabuelo",
2770
+ "trastatarabuela",
2771
+ "trastatarabuelo/trastatarabuela"
2772
+ );
2773
+ }
2774
+ return pick3(
2775
+ sex,
2776
+ `abuelo (${level}.\xBA)`,
2777
+ `abuela (${level}.\xAA)`,
2778
+ `abuelo/abuela (${level}.\xBA)`
2779
+ );
2519
2780
  }
2520
2781
  child() {
2521
- const prefix = this.directPrefix();
2522
- if (this.personN?.isMale()) {
2523
- return `${prefix}hijo`;
2782
+ const level = Math.abs(this.pathN?.level ?? 0);
2783
+ const sex = sexOf3(this.personN);
2784
+ if (level <= 1) {
2785
+ return pick3(sex, "hijo", "hija", "hijo/hija");
2524
2786
  }
2525
- if (this.personN?.isFemale()) {
2526
- return `${prefix}hija`;
2787
+ if (level === 2) {
2788
+ return pick3(sex, "nieto", "nieta", "nieto/nieta");
2527
2789
  }
2528
- return `${prefix}hijo/hija`;
2529
- }
2530
- sibling() {
2531
- if (this.personN?.isMale()) {
2532
- return "hermano";
2790
+ if (level === 3) {
2791
+ return pick3(sex, "bisnieto", "bisnieta", "bisnieto/bisnieta");
2533
2792
  }
2534
- if (this.personN?.isFemale()) {
2535
- return "hermana";
2793
+ if (level === 4) {
2794
+ return pick3(
2795
+ sex,
2796
+ "tataranieto",
2797
+ "tataranieta",
2798
+ "tataranieto/tataranieta"
2799
+ );
2800
+ }
2801
+ if (level === 5) {
2802
+ return pick3(
2803
+ sex,
2804
+ "trastataranieto",
2805
+ "trastataranieta",
2806
+ "trastataranieto/trastataranieta"
2807
+ );
2536
2808
  }
2537
- return "hermano/hermana";
2809
+ return pick3(
2810
+ sex,
2811
+ `nieto (${level}.\xBA)`,
2812
+ `nieta (${level}.\xAA)`,
2813
+ `nieto/nieta (${level}.\xBA)`
2814
+ );
2815
+ }
2816
+ sibling() {
2817
+ return pick3(sexOf3(this.personN), "hermano", "hermana", "hermano/hermana");
2538
2818
  }
2539
2819
  halfBlood(relation) {
2540
2820
  if (!relation || !this.isHalfBlood) {
@@ -2549,40 +2829,30 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2549
2829
  return `medio/a ${relation}`;
2550
2830
  }
2551
2831
  spouse() {
2552
- if (this.personN?.isMale()) {
2553
- return "esposo";
2554
- }
2555
- if (this.personN?.isFemale()) {
2556
- return "esposa";
2557
- }
2558
- return "c\xF3nyuge";
2832
+ return pick3(sexOf3(this.personN), "esposo", "esposa", "c\xF3nyuge");
2559
2833
  }
2560
2834
  ofSpouse(relation) {
2561
2835
  if (!relation) {
2562
2836
  return "";
2563
2837
  }
2564
- const spouse = this.path?.[1].indi;
2565
- let spouseType = "c\xF3nyuge";
2566
- if (spouse?.isMale()) {
2567
- spouseType = "esposo";
2568
- }
2569
- if (spouse?.isFemale()) {
2570
- spouseType = "esposa";
2571
- }
2572
- return `${relation} del ${spouseType}`;
2838
+ const spouseType = pick3(
2839
+ sexOf3(this.path?.[1].indi),
2840
+ "esposo",
2841
+ "esposa",
2842
+ "c\xF3nyuge"
2843
+ );
2844
+ return `${relation} ${ofSpousePrep2(spouseType)}${spouseType}`;
2573
2845
  }
2574
2846
  spouseOf(relation) {
2575
2847
  if (!relation) {
2576
2848
  return "";
2577
2849
  }
2578
- const spouse = this.path?.[this.path.length - 1].indi;
2579
- let spouseType = "c\xF3nyuge";
2580
- if (spouse?.isMale()) {
2581
- spouseType = "esposo";
2582
- }
2583
- if (spouse?.isFemale()) {
2584
- spouseType = "esposa";
2585
- }
2850
+ const spouseType = pick3(
2851
+ sexOf3(this.path?.[this.path.length - 1].indi),
2852
+ "esposo",
2853
+ "esposa",
2854
+ "c\xF3nyuge"
2855
+ );
2586
2856
  return `${spouseType} de ${relation}`;
2587
2857
  }
2588
2858
  of(relation) {
@@ -2600,8 +2870,8 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2600
2870
  if (!name || !relation) {
2601
2871
  return relation ?? "";
2602
2872
  }
2603
- if (relation.includes(" del ") || relation.includes(" de ")) {
2604
- return relation.replace(/ (del|de) /, ` $1 ${name} `);
2873
+ if (relation.includes(" del ") || relation.includes(" de la ") || relation.includes(" de ")) {
2874
+ return relation.replace(/ (del|de la|de) /, ` $1 ${name} `);
2605
2875
  }
2606
2876
  return `${relation} de ${name}`;
2607
2877
  }
@@ -2631,7 +2901,20 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2631
2901
  if (!relation || !this.pathN?.relation) {
2632
2902
  return relation ?? "";
2633
2903
  }
2634
- return `${this.pathN.relation} ${relation}`;
2904
+ const mapped = parentRelationsEs[this.pathN.relation]?.[relation];
2905
+ if (mapped) {
2906
+ return mapped;
2907
+ }
2908
+ if (this.pathN.relation === "step") {
2909
+ return `${relation} pol\xEDtico`;
2910
+ }
2911
+ if (this.pathN.relation === "adopted") {
2912
+ return `${relation} adoptivo`;
2913
+ }
2914
+ if (this.pathN.relation === "foster") {
2915
+ return `${relation} de acogida`;
2916
+ }
2917
+ return relation;
2635
2918
  }
2636
2919
  };
2637
2920
 
@@ -2640,15 +2923,35 @@ var InLawsRu = {
2640
2923
  "\u0441\u0443\u043F\u0440\u0443\u0433(?:\u0430)? (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u0437\u044F\u0442\u044C/\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
2641
2924
  "\u0436\u0435\u043D\u0430 (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
2642
2925
  "\u043C\u0443\u0436 (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u0437\u044F\u0442\u044C",
2643
- "\u043C\u0430\u0442\u044C (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0451\u0449\u0430",
2644
- "\u043E\u0442\u0435\u0446 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0435\u0441\u0442\u044C",
2645
- "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0435\u0441\u0442\u044C/\u0442\u0451\u0449\u0430",
2926
+ "\u043C\u0430\u0442\u044C \u0436\u0435\u043D\u044B": "\u0442\u0451\u0449\u0430",
2927
+ "\u043C\u0430\u0442\u044C \u043C\u0443\u0436\u0430": "\u0441\u0432\u0435\u043A\u0440\u043E\u0432\u044C",
2928
+ "\u043C\u0430\u0442\u044C \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0442\u0451\u0449\u0430/\u0441\u0432\u0435\u043A\u0440\u043E\u0432\u044C",
2929
+ "\u043E\u0442\u0435\u0446 \u0436\u0435\u043D\u044B": "\u0442\u0435\u0441\u0442\u044C",
2930
+ "\u043E\u0442\u0435\u0446 \u043C\u0443\u0436\u0430": "\u0441\u0432\u0451\u043A\u043E\u0440",
2931
+ "\u043E\u0442\u0435\u0446 \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0442\u0435\u0441\u0442\u044C/\u0441\u0432\u0451\u043A\u043E\u0440",
2932
+ "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C \u0436\u0435\u043D\u044B": "\u0442\u0435\u0441\u0442\u044C/\u0442\u0451\u0449\u0430",
2933
+ "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C \u043C\u0443\u0436\u0430": "\u0441\u0432\u0451\u043A\u043E\u0440/\u0441\u0432\u0435\u043A\u0440\u043E\u0432\u044C",
2934
+ "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0442\u0435\u0441\u0442\u044C/\u0442\u0451\u0449\u0430",
2646
2935
  "\u0436\u0435\u043D\u0430 (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
2647
2936
  "\u043C\u0443\u0436 (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u0437\u044F\u0442\u044C",
2648
2937
  "\u0441\u0443\u043F\u0440\u0443\u0433(?:\u0430)? (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u0437\u044F\u0442\u044C/\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
2649
- "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0435\u0441\u0442\u0440\u0430 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0437\u043E\u043B\u043E\u0432\u043A\u0430",
2650
- "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0431\u0440\u0430\u0442 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0448\u0443\u0440\u0438\u043D",
2651
- "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0438\u0431\u043B\u0438\u043D\u0433 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0448\u0443\u0440\u0438\u043D/\u0437\u043E\u043B\u043E\u0432\u043A\u0430"
2938
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0435\u0441\u0442\u0440\u0430 \u0436\u0435\u043D\u044B": "\u0441\u0432\u043E\u044F\u0447\u0435\u043D\u0438\u0446\u0430",
2939
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0435\u0441\u0442\u0440\u0430 \u043C\u0443\u0436\u0430": "\u0437\u043E\u043B\u043E\u0432\u043A\u0430",
2940
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0435\u0441\u0442\u0440\u0430 \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0441\u0432\u043E\u044F\u0447\u0435\u043D\u0438\u0446\u0430/\u0437\u043E\u043B\u043E\u0432\u043A\u0430",
2941
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0431\u0440\u0430\u0442 \u0436\u0435\u043D\u044B": "\u0448\u0443\u0440\u0438\u043D",
2942
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0431\u0440\u0430\u0442 \u043C\u0443\u0436\u0430": "\u0434\u0435\u0432\u0435\u0440\u044C",
2943
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0431\u0440\u0430\u0442 \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0448\u0443\u0440\u0438\u043D/\u0434\u0435\u0432\u0435\u0440\u044C",
2944
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0438\u0431\u043B\u0438\u043D\u0433 \u0436\u0435\u043D\u044B": "\u0448\u0443\u0440\u0438\u043D/\u0441\u0432\u043E\u044F\u0447\u0435\u043D\u0438\u0446\u0430",
2945
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0438\u0431\u043B\u0438\u043D\u0433 \u043C\u0443\u0436\u0430": "\u0434\u0435\u0432\u0435\u0440\u044C/\u0437\u043E\u043B\u043E\u0432\u043A\u0430",
2946
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0438\u0431\u043B\u0438\u043D\u0433 \u0441\u0443\u043F\u0440\u0443\u0433\u0430": "\u0448\u0443\u0440\u0438\u043D/\u0437\u043E\u043B\u043E\u0432\u043A\u0430"
2947
+ };
2948
+ var parentRelationsRu = {
2949
+ step: {
2950
+ \u043E\u0442\u0435\u0446: "\u043E\u0442\u0447\u0438\u043C",
2951
+ \u043C\u0430\u0442\u044C: "\u043C\u0430\u0447\u0435\u0445\u0430",
2952
+ \u0441\u044B\u043D: "\u043F\u0430\u0441\u044B\u043D\u043E\u043A",
2953
+ \u0434\u043E\u0447\u044C: "\u043F\u0430\u0434\u0447\u0435\u0440\u0438\u0446\u0430"
2954
+ }
2652
2955
  };
2653
2956
 
2654
2957
  // src/kinship-translator/kinship-translator.ru.ts
@@ -2679,7 +2982,7 @@ var cousinWord = (degree, sex) => {
2679
2982
  return `${stem}\u044B\u0439 \u0431\u0440\u0430\u0442/\u0441\u0435\u0441\u0442\u0440\u0430`;
2680
2983
  };
2681
2984
  var praRepeat = (count) => count > 0 ? "\u043F\u0440\u0430".repeat(count) : "";
2682
- var sexOf = (person) => {
2985
+ var sexOf4 = (person) => {
2683
2986
  if (person?.isMale?.()) {
2684
2987
  return "m";
2685
2988
  }
@@ -2694,7 +2997,7 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2694
2997
  if (degree > 0) {
2695
2998
  degree = degree - 1;
2696
2999
  }
2697
- return cousinWord(degree, sexOf(this.personN));
3000
+ return cousinWord(degree, sexOf4(this.personN));
2698
3001
  }
2699
3002
  removal() {
2700
3003
  const level = this.pathN?.level ?? 0;
@@ -2706,35 +3009,53 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2706
3009
  return level < 0 ? this.nibling() : this.auncle();
2707
3010
  }
2708
3011
  const removed = Math.abs(level);
2709
- return `${cousinWord(degree, sexOf(this.personN))} (${removed}\xD7 \u0447\u0435\u0440\u0435\u0437 \u043F\u043E\u043A\u043E\u043B\u0435\u043D\u0438\u0435)`;
3012
+ return `${cousinWord(degree, sexOf4(this.personN))} (${removed}\xD7 \u0447\u0435\u0440\u0435\u0437 \u043F\u043E\u043A\u043E\u043B\u0435\u043D\u0438\u0435)`;
2710
3013
  }
2711
3014
  auncle() {
2712
3015
  const level = Math.abs(this.pathN?.level ?? 0);
2713
- const pra = praRepeat(Math.max(0, level - 2));
2714
- const sex = sexOf(this.personN);
3016
+ const sex = sexOf4(this.personN);
3017
+ if (level <= 1) {
3018
+ if (sex === "m") {
3019
+ return "\u0434\u044F\u0434\u044F";
3020
+ }
3021
+ if (sex === "f") {
3022
+ return "\u0442\u0451\u0442\u044F";
3023
+ }
3024
+ return "\u0434\u044F\u0434\u044F/\u0442\u0451\u0442\u044F";
3025
+ }
3026
+ const pra = praRepeat(level - 2);
2715
3027
  if (sex === "m") {
2716
- return `${pra}\u0434\u044F\u0434\u044F`;
3028
+ return `\u0434\u0432\u043E\u044E\u0440\u043E\u0434\u043D\u044B\u0439 ${pra}\u0434\u0435\u0434`;
2717
3029
  }
2718
3030
  if (sex === "f") {
2719
- return `${pra}\u0442\u0451\u0442\u044F`;
3031
+ return `\u0434\u0432\u043E\u044E\u0440\u043E\u0434\u043D\u0430\u044F ${pra}\u0431\u0430\u0431\u0443\u0448\u043A\u0430`;
2720
3032
  }
2721
- return `${pra}\u0434\u044F\u0434\u044F/\u0442\u0451\u0442\u044F`;
3033
+ return `\u0434\u0432\u043E\u044E\u0440\u043E\u0434\u043D\u044B\u0439 ${pra}\u0434\u0435\u0434/\u0431\u0430\u0431\u0443\u0448\u043A\u0430`;
2722
3034
  }
2723
3035
  nibling() {
2724
3036
  const level = Math.abs(this.pathN?.level ?? 0);
2725
- const pra = praRepeat(Math.max(0, level - 2));
2726
- const sex = sexOf(this.personN);
3037
+ const sex = sexOf4(this.personN);
3038
+ if (level <= 1) {
3039
+ if (sex === "m") {
3040
+ return "\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A";
3041
+ }
3042
+ if (sex === "f") {
3043
+ return "\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430";
3044
+ }
3045
+ return "\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A/\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430";
3046
+ }
3047
+ const pra = praRepeat(level - 2);
2727
3048
  if (sex === "m") {
2728
- return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A`;
3049
+ return `${pra}\u0432\u043D\u0443\u0447\u0430\u0442\u044B\u0439 \u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A`;
2729
3050
  }
2730
3051
  if (sex === "f") {
2731
- return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
3052
+ return `${pra}\u0432\u043D\u0443\u0447\u0430\u0442\u0430\u044F \u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
2732
3053
  }
2733
- return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A/\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
3054
+ return `${pra}\u0432\u043D\u0443\u0447\u0430\u0442\u044B\u0439 \u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A/\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
2734
3055
  }
2735
3056
  parent() {
2736
3057
  const level = Math.abs(this.pathN?.level ?? 0);
2737
- const sex = sexOf(this.personN);
3058
+ const sex = sexOf4(this.personN);
2738
3059
  if (level <= 1) {
2739
3060
  if (sex === "m") {
2740
3061
  return "\u043E\u0442\u0435\u0446";
@@ -2764,7 +3085,7 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2764
3085
  }
2765
3086
  child() {
2766
3087
  const level = Math.abs(this.pathN?.level ?? 0);
2767
- const sex = sexOf(this.personN);
3088
+ const sex = sexOf4(this.personN);
2768
3089
  if (level <= 1) {
2769
3090
  if (sex === "m") {
2770
3091
  return "\u0441\u044B\u043D";
@@ -2793,14 +3114,14 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2793
3114
  return `${pra}\u0432\u043D\u0443\u043A/\u0432\u043D\u0443\u0447\u043A\u0430`;
2794
3115
  }
2795
3116
  sibling() {
2796
- const sex = sexOf(this.personN);
3117
+ const sex = sexOf4(this.personN);
2797
3118
  if (sex === "m") {
2798
3119
  return "\u0431\u0440\u0430\u0442";
2799
3120
  }
2800
3121
  if (sex === "f") {
2801
3122
  return "\u0441\u0435\u0441\u0442\u0440\u0430";
2802
3123
  }
2803
- return "\u0441\u0438\u0431\u043B\u0438\u043D\u0433";
3124
+ return "\u0431\u0440\u0430\u0442/\u0441\u0435\u0441\u0442\u0440\u0430";
2804
3125
  }
2805
3126
  halfBlood(relation) {
2806
3127
  if (!relation || !this.isHalfBlood) {
@@ -2814,7 +3135,7 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2814
3135
  return `\u0441\u0432\u043E\u0434\u043D\u044B\u0439 ${relation}`;
2815
3136
  }
2816
3137
  spouse() {
2817
- const sex = sexOf(this.personN);
3138
+ const sex = sexOf4(this.personN);
2818
3139
  if (sex === "m") {
2819
3140
  return "\u043C\u0443\u0436";
2820
3141
  }
@@ -2828,7 +3149,7 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2828
3149
  return "";
2829
3150
  }
2830
3151
  const spouse = this.path?.[1].indi;
2831
- const sex = sexOf(spouse);
3152
+ const sex = sexOf4(spouse);
2832
3153
  const spouseType = sex === "m" ? "\u043C\u0443\u0436" : sex === "f" ? "\u0436\u0435\u043D\u0430" : "\u0441\u0443\u043F\u0440\u0443\u0433";
2833
3154
  return `${relation} ${toGenitive(spouseType)}`;
2834
3155
  }
@@ -2837,7 +3158,7 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2837
3158
  return "";
2838
3159
  }
2839
3160
  const spouse = this.path?.[this.path.length - 1].indi;
2840
- const sex = sexOf(spouse);
3161
+ const sex = sexOf4(spouse);
2841
3162
  const spouseType = sex === "m" ? "\u043C\u0443\u0436" : sex === "f" ? "\u0436\u0435\u043D\u0430" : "\u0441\u0443\u043F\u0440\u0443\u0433";
2842
3163
  return `${spouseType} ${toGenitive(relation)}`;
2843
3164
  }
@@ -2874,7 +3195,22 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2874
3195
  if (!relation || !this.pathN?.relation) {
2875
3196
  return relation ?? "";
2876
3197
  }
2877
- return `${this.pathN.relation} ${relation}`;
3198
+ const mapped = parentRelationsRu[this.pathN.relation]?.[relation];
3199
+ if (mapped) {
3200
+ return mapped;
3201
+ }
3202
+ if (this.pathN.relation === "step") {
3203
+ return `\u043D\u0435\u0440\u043E\u0434\u043D\u043E\u0439 ${relation}`;
3204
+ }
3205
+ if (this.pathN.relation === "adopted") {
3206
+ return /сестра|дочь|мать|тётя|бабушка|жена|племянница|внучка/.test(
3207
+ relation
3208
+ ) ? `\u043F\u0440\u0438\u0451\u043C\u043D\u0430\u044F ${relation}` : `\u043F\u0440\u0438\u0451\u043C\u043D\u044B\u0439 ${relation}`;
3209
+ }
3210
+ if (this.pathN.relation === "foster") {
3211
+ return `\u043F\u0440\u0438\u0451\u043C\u043D\u044B\u0439 ${relation}`;
3212
+ }
3213
+ return relation;
2878
3214
  }
2879
3215
  };
2880
3216
 
@@ -2898,7 +3234,7 @@ var InLawsJa = {
2898
3234
  };
2899
3235
 
2900
3236
  // src/kinship-translator/kinship-translator.ja.ts
2901
- var sexOf2 = (person) => {
3237
+ var sexOf5 = (person) => {
2902
3238
  if (person?.isMale?.()) {
2903
3239
  return "m";
2904
3240
  }
@@ -2907,7 +3243,7 @@ var sexOf2 = (person) => {
2907
3243
  }
2908
3244
  return "n";
2909
3245
  };
2910
- var pick = (sex, male, female, neutral) => {
3246
+ var pick4 = (sex, male, female, neutral) => {
2911
3247
  if (sex === "m") {
2912
3248
  return male;
2913
3249
  }
@@ -2920,18 +3256,18 @@ var lineal = (level, sex, kind) => {
2920
3256
  const L = Math.max(1, level);
2921
3257
  if (kind === "asc") {
2922
3258
  if (L <= 1) {
2923
- return pick(sex, "\u7236", "\u6BCD", "\u89AA");
3259
+ return pick4(sex, "\u7236", "\u6BCD", "\u89AA");
2924
3260
  }
2925
3261
  if (L === 2) {
2926
- return pick(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
3262
+ return pick4(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
2927
3263
  }
2928
3264
  if (L === 3) {
2929
- return pick(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
3265
+ return pick4(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
2930
3266
  }
2931
3267
  if (L === 4) {
2932
- return pick(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
3268
+ return pick4(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
2933
3269
  }
2934
- return pick(
3270
+ return pick4(
2935
3271
  sex,
2936
3272
  `${L - 1}\u4E16\u306E\u7956\u7236`,
2937
3273
  `${L - 1}\u4E16\u306E\u7956\u6BCD`,
@@ -2939,7 +3275,7 @@ var lineal = (level, sex, kind) => {
2939
3275
  );
2940
3276
  }
2941
3277
  if (L <= 1) {
2942
- return pick(sex, "\u606F\u5B50", "\u5A18", "\u5B50");
3278
+ return pick4(sex, "\u606F\u5B50", "\u5A18", "\u5B50");
2943
3279
  }
2944
3280
  if (L === 2) {
2945
3281
  return "\u5B6B";
@@ -2986,52 +3322,52 @@ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
2986
3322
  }
2987
3323
  auncle() {
2988
3324
  const level = Math.abs(this.pathN?.level ?? 0);
2989
- const sex = sexOf2(this.personN);
2990
- if (level <= 2) {
2991
- return pick(sex, "\u304A\u3058", "\u304A\u3070", "\u304A\u3058/\u304A\u3070");
3325
+ const sex = sexOf5(this.personN);
3326
+ if (level <= 1) {
3327
+ return pick4(sex, "\u304A\u3058", "\u304A\u3070", "\u304A\u3058/\u304A\u3070");
2992
3328
  }
2993
- if (level === 3) {
2994
- return pick(sex, "\u5927\u304A\u3058", "\u5927\u304A\u3070", "\u5927\u304A\u3058/\u5927\u304A\u3070");
3329
+ if (level === 2) {
3330
+ return pick4(sex, "\u5927\u304A\u3058", "\u5927\u304A\u3070", "\u5927\u304A\u3058/\u5927\u304A\u3070");
2995
3331
  }
2996
- return pick(
3332
+ return pick4(
2997
3333
  sex,
2998
- `${level - 2}\u4EE3\u524D\u306E\u304A\u3058`,
2999
- `${level - 2}\u4EE3\u524D\u306E\u304A\u3070`,
3000
- `${level - 2}\u4EE3\u524D\u306E\u304A\u3058/\u304A\u3070`
3334
+ `${level - 1}\u4EE3\u524D\u306E\u304A\u3058`,
3335
+ `${level - 1}\u4EE3\u524D\u306E\u304A\u3070`,
3336
+ `${level - 1}\u4EE3\u524D\u306E\u304A\u3058/\u304A\u3070`
3001
3337
  );
3002
3338
  }
3003
3339
  nibling() {
3004
3340
  const level = Math.abs(this.pathN?.level ?? 0);
3005
- const sex = sexOf2(this.personN);
3006
- if (level <= 2) {
3007
- return pick(sex, "\u7525", "\u59EA", "\u7525/\u59EA");
3341
+ const sex = sexOf5(this.personN);
3342
+ if (level <= 1) {
3343
+ return pick4(sex, "\u7525", "\u59EA", "\u7525/\u59EA");
3008
3344
  }
3009
- if (level === 3) {
3010
- return pick(sex, "\u5927\u7525", "\u5927\u59EA", "\u5927\u7525/\u5927\u59EA");
3345
+ if (level === 2) {
3346
+ return pick4(sex, "\u5927\u7525", "\u5927\u59EA", "\u5927\u7525/\u5927\u59EA");
3011
3347
  }
3012
- return pick(
3348
+ return pick4(
3013
3349
  sex,
3014
- `${level - 2}\u4EE3\u4E0B\u306E\u7525`,
3015
- `${level - 2}\u4EE3\u4E0B\u306E\u59EA`,
3016
- `${level - 2}\u4EE3\u4E0B\u306E\u7525/\u59EA`
3350
+ `${level - 1}\u4EE3\u4E0B\u306E\u7525`,
3351
+ `${level - 1}\u4EE3\u4E0B\u306E\u59EA`,
3352
+ `${level - 1}\u4EE3\u4E0B\u306E\u7525/\u59EA`
3017
3353
  );
3018
3354
  }
3019
3355
  parent() {
3020
3356
  return lineal(
3021
3357
  Math.abs(this.pathN?.level ?? 0),
3022
- sexOf2(this.personN),
3358
+ sexOf5(this.personN),
3023
3359
  "asc"
3024
3360
  );
3025
3361
  }
3026
3362
  child() {
3027
3363
  return lineal(
3028
3364
  Math.abs(this.pathN?.level ?? 0),
3029
- sexOf2(this.personN),
3365
+ sexOf5(this.personN),
3030
3366
  "desc"
3031
3367
  );
3032
3368
  }
3033
3369
  sibling() {
3034
- return pick(sexOf2(this.personN), "\u5144\u5F1F", "\u59C9\u59B9", "\u5144\u5F1F\u59C9\u59B9");
3370
+ return pick4(sexOf5(this.personN), "\u5144\u5F1F", "\u59C9\u59B9", "\u5144\u5F1F\u59C9\u59B9");
3035
3371
  }
3036
3372
  halfBlood(relation) {
3037
3373
  if (!relation || !this.isHalfBlood) {
@@ -3040,14 +3376,14 @@ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
3040
3376
  return `\u7570\u7236\u6BCD\u306E${relation}`;
3041
3377
  }
3042
3378
  spouse() {
3043
- return pick(sexOf2(this.personN), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3379
+ return pick4(sexOf5(this.personN), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3044
3380
  }
3045
3381
  ofSpouse(relation) {
3046
3382
  if (!relation) {
3047
3383
  return "";
3048
3384
  }
3049
- const spouseType = pick(
3050
- sexOf2(this.path?.[1].indi),
3385
+ const spouseType = pick4(
3386
+ sexOf5(this.path?.[1].indi),
3051
3387
  "\u592B",
3052
3388
  "\u59BB",
3053
3389
  "\u914D\u5076\u8005"
@@ -3059,7 +3395,7 @@ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
3059
3395
  return "";
3060
3396
  }
3061
3397
  const spouse = this.path?.[this.path.length - 1].indi;
3062
- const spouseType = pick(sexOf2(spouse), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3398
+ const spouseType = pick4(sexOf5(spouse), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3063
3399
  return `${relation}\u306E${spouseType}`;
3064
3400
  }
3065
3401
  of(relation) {
@@ -3095,7 +3431,28 @@ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
3095
3431
  if (!relation || !this.pathN?.relation) {
3096
3432
  return relation ?? "";
3097
3433
  }
3098
- return `${this.pathN.relation}\u306E${relation}`;
3434
+ if (this.pathN.relation === "step") {
3435
+ if (relation === "\u7236") {
3436
+ return "\u7EE7\u7236";
3437
+ }
3438
+ if (relation === "\u6BCD") {
3439
+ return "\u7D99\u6BCD";
3440
+ }
3441
+ if (relation === "\u606F\u5B50") {
3442
+ return "\u7D99\u5B50";
3443
+ }
3444
+ if (relation === "\u5A18") {
3445
+ return "\u7D99\u5A18";
3446
+ }
3447
+ return `\u7D99${relation}`;
3448
+ }
3449
+ if (this.pathN.relation === "adopted") {
3450
+ return `\u990A\u5B50\u306E${relation}`;
3451
+ }
3452
+ if (this.pathN.relation === "foster") {
3453
+ return `\u91CC\u89AA\u306E${relation}`;
3454
+ }
3455
+ return relation;
3099
3456
  }
3100
3457
  };
3101
3458
 
@@ -3104,22 +3461,32 @@ var InLawsZh = {
3104
3461
  "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u914D\u5076": "\u513F\u5AB3/\u5973\u5A7F",
3105
3462
  "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u59BB\u5B50": "\u513F\u5AB3",
3106
3463
  "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u4E08\u592B": "\u5973\u5A7F",
3107
- "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD/\u5A46\u5A46",
3108
- "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u4EB2": "\u5CB3\u7236/\u516C\u516C",
3109
- "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD/\u516C\u516C\u5A46\u5A46",
3464
+ "\u59BB\u5B50\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD",
3465
+ "\u4E08\u592B\u7684\u6BCD\u4EB2": "\u5A46\u5A46",
3466
+ "(\u914D\u5076)\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD/\u5A46\u5A46",
3467
+ "\u59BB\u5B50\u7684\u7236\u4EB2": "\u5CB3\u7236",
3468
+ "\u4E08\u592B\u7684\u7236\u4EB2": "\u516C\u516C",
3469
+ "(\u914D\u5076)\u7684\u7236\u4EB2": "\u5CB3\u7236/\u516C\u516C",
3470
+ "\u59BB\u5B50\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD",
3471
+ "\u4E08\u592B\u7684\u7236\u6BCD": "\u516C\u516C\u5A46\u5A46",
3472
+ "(\u914D\u5076)\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD/\u516C\u516C\u5A46\u5A46",
3110
3473
  "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u59BB\u5B50": "\u5AC2\u5B50/\u5F1F\u59B9",
3111
3474
  "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u4E08\u592B": "\u59D0\u592B/\u59B9\u592B",
3112
3475
  "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u914D\u5076": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
3113
3476
  "(\u5F02\u7236\u6BCD\u7684)?\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59D0\u592B/\u59B9\u592B",
3114
3477
  "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u5AC2\u5B50/\u5F1F\u59B9",
3115
3478
  "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
3116
- "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u59D0\u59B9": "\u59D1\u5B50/\u59E8\u5B50",
3117
- "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4/\u5185\u5144/\u5185\u5F1F",
3479
+ "(\u5F02\u7236\u6BCD\u7684)?\u59BB\u5B50\u7684\u59D0\u59B9": "\u59E8\u5B50",
3480
+ "(\u5F02\u7236\u6BCD\u7684)?\u4E08\u592B\u7684\u59D0\u59B9": "\u59D1\u5B50",
3481
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076)\u7684\u59D0\u59B9": "\u59D1\u5B50/\u59E8\u5B50",
3482
+ "(\u5F02\u7236\u6BCD\u7684)?\u59BB\u5B50\u7684\u5144\u5F1F": "\u5185\u5144/\u5185\u5F1F",
3483
+ "(\u5F02\u7236\u6BCD\u7684)?\u4E08\u592B\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4",
3484
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076)\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4/\u5185\u5144/\u5185\u5F1F",
3118
3485
  "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F\u59D0\u59B9": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9"
3119
3486
  };
3120
3487
 
3121
3488
  // src/kinship-translator/kinship-translator.zh.ts
3122
- var sexOf3 = (person) => {
3489
+ var sexOf6 = (person) => {
3123
3490
  if (person?.isMale?.()) {
3124
3491
  return "m";
3125
3492
  }
@@ -3128,7 +3495,7 @@ var sexOf3 = (person) => {
3128
3495
  }
3129
3496
  return "n";
3130
3497
  };
3131
- var pick2 = (sex, male, female, neutral) => {
3498
+ var pick5 = (sex, male, female, neutral) => {
3132
3499
  if (sex === "m") {
3133
3500
  return male;
3134
3501
  }
@@ -3141,41 +3508,41 @@ var lineal2 = (level, sex, kind) => {
3141
3508
  const L = Math.max(1, level);
3142
3509
  if (kind === "asc") {
3143
3510
  if (L <= 1) {
3144
- return pick2(sex, "\u7236\u4EB2", "\u6BCD\u4EB2", "\u7236\u6BCD");
3511
+ return pick5(sex, "\u7236\u4EB2", "\u6BCD\u4EB2", "\u7236\u6BCD");
3145
3512
  }
3146
3513
  if (L === 2) {
3147
- return pick2(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
3514
+ return pick5(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
3148
3515
  }
3149
3516
  if (L === 3) {
3150
- return pick2(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
3517
+ return pick5(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
3151
3518
  }
3152
3519
  if (L === 4) {
3153
- return pick2(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
3520
+ return pick5(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
3154
3521
  }
3155
- return pick2(sex, `${L}\u4E16\u7956`, `${L}\u4E16\u7956\u6BCD`, `${L}\u4E16\u7956\u7236\u6BCD`);
3522
+ return pick5(sex, `${L}\u4E16\u7956`, `${L}\u4E16\u7956\u6BCD`, `${L}\u4E16\u7956\u7236\u6BCD`);
3156
3523
  }
3157
3524
  if (L <= 1) {
3158
- return pick2(sex, "\u513F\u5B50", "\u5973\u513F", "\u5B50\u5973");
3525
+ return pick5(sex, "\u513F\u5B50", "\u5973\u513F", "\u5B50\u5973");
3159
3526
  }
3160
3527
  if (L === 2) {
3161
- return pick2(sex, "\u5B59\u5B50", "\u5B59\u5973", "\u5B59\u5B50\u5973");
3528
+ return pick5(sex, "\u5B59\u5B50", "\u5B59\u5973", "\u5B59\u5B50\u5973");
3162
3529
  }
3163
3530
  if (L === 3) {
3164
- return pick2(sex, "\u66FE\u5B59", "\u66FE\u5B59\u5973", "\u66FE\u5B59\u5B50\u5973");
3531
+ return pick5(sex, "\u66FE\u5B59", "\u66FE\u5B59\u5973", "\u66FE\u5B59\u5B50\u5973");
3165
3532
  }
3166
3533
  if (L === 4) {
3167
- return pick2(sex, "\u7384\u5B59", "\u7384\u5B59\u5973", "\u7384\u5B59\u5B50\u5973");
3534
+ return pick5(sex, "\u7384\u5B59", "\u7384\u5B59\u5973", "\u7384\u5B59\u5B50\u5973");
3168
3535
  }
3169
- return pick2(sex, `${L}\u4E16\u5B59`, `${L}\u4E16\u5B59\u5973`, `${L}\u4E16\u5B59\u5B50\u5973`);
3536
+ return pick5(sex, `${L}\u4E16\u5B59`, `${L}\u4E16\u5B59\u5973`, `${L}\u4E16\u5B59\u5B50\u5973`);
3170
3537
  };
3171
3538
  var cousinPlain2 = (degree, sex) => {
3172
3539
  if (degree <= 1) {
3173
- return pick2(sex, "\u5802\u8868\u5144\u5F1F", "\u5802\u8868\u59D0\u59B9", "\u5802\u8868\u4EB2");
3540
+ return pick5(sex, "\u5802\u8868\u5144\u5F1F", "\u5802\u8868\u59D0\u59B9", "\u5802\u8868\u4EB2");
3174
3541
  }
3175
3542
  if (degree === 2) {
3176
- return pick2(sex, "\u4ECE\u5802\u8868\u5144\u5F1F", "\u4ECE\u5802\u8868\u59D0\u59B9", "\u4ECE\u5802\u8868\u4EB2");
3543
+ return pick5(sex, "\u4ECE\u5802\u8868\u5144\u5F1F", "\u4ECE\u5802\u8868\u59D0\u59B9", "\u4ECE\u5802\u8868\u4EB2");
3177
3544
  }
3178
- return pick2(
3545
+ return pick5(
3179
3546
  sex,
3180
3547
  `${degree}\u4EE3\u5802\u8868\u5144\u5F1F`,
3181
3548
  `${degree}\u4EE3\u5802\u8868\u59D0\u59B9`,
@@ -3188,7 +3555,7 @@ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3188
3555
  if (degree > 0) {
3189
3556
  degree = degree - 1;
3190
3557
  }
3191
- return cousinPlain2(degree, sexOf3(this.personN));
3558
+ return cousinPlain2(degree, sexOf6(this.personN));
3192
3559
  }
3193
3560
  removal() {
3194
3561
  const level = this.pathN?.level ?? 0;
@@ -3200,56 +3567,56 @@ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3200
3567
  return level < 0 ? this.nibling() : this.auncle();
3201
3568
  }
3202
3569
  const removed = Math.abs(level);
3203
- return `${cousinPlain2(degree, sexOf3(this.personN))}\uFF08\u9694${removed}\u4EE3\uFF09`;
3570
+ return `${cousinPlain2(degree, sexOf6(this.personN))}\uFF08\u9694${removed}\u4EE3\uFF09`;
3204
3571
  }
3205
3572
  auncle() {
3206
3573
  const level = Math.abs(this.pathN?.level ?? 0);
3207
- const sex = sexOf3(this.personN);
3208
- if (level <= 2) {
3209
- return pick2(sex, "\u53D4\u53D4", "\u963F\u59E8", "\u53D4\u4F2F/\u59D1\u59E8");
3574
+ const sex = sexOf6(this.personN);
3575
+ if (level <= 1) {
3576
+ return pick5(sex, "\u53D4\u53D4", "\u963F\u59E8", "\u53D4\u4F2F/\u59D1\u59E8");
3210
3577
  }
3211
- if (level === 3) {
3212
- return pick2(sex, "\u4F2F\u53D4\u7956\u7236", "\u59D1\u7956\u6BCD", "\u4F2F\u53D4\u7956\u7236\u6BCD");
3578
+ if (level === 2) {
3579
+ return pick5(sex, "\u4F2F\u53D4\u7956\u7236", "\u59D1\u7956\u6BCD", "\u4F2F\u53D4\u7956\u7236\u6BCD");
3213
3580
  }
3214
- return pick2(
3581
+ return pick5(
3215
3582
  sex,
3216
- `${level - 2}\u4EE3\u524D\u7684\u53D4\u53D4`,
3217
- `${level - 2}\u4EE3\u524D\u7684\u963F\u59E8`,
3218
- `${level - 2}\u4EE3\u524D\u7684\u53D4\u4F2F/\u59D1\u59E8`
3583
+ `${level - 1}\u4EE3\u524D\u7684\u53D4\u53D4`,
3584
+ `${level - 1}\u4EE3\u524D\u7684\u963F\u59E8`,
3585
+ `${level - 1}\u4EE3\u524D\u7684\u53D4\u4F2F/\u59D1\u59E8`
3219
3586
  );
3220
3587
  }
3221
3588
  nibling() {
3222
3589
  const level = Math.abs(this.pathN?.level ?? 0);
3223
- const sex = sexOf3(this.personN);
3224
- if (level <= 2) {
3225
- return pick2(sex, "\u4F84\u5B50", "\u4F84\u5973", "\u4F84\u5B50\u5973");
3590
+ const sex = sexOf6(this.personN);
3591
+ if (level <= 1) {
3592
+ return pick5(sex, "\u4F84\u5B50", "\u4F84\u5973", "\u4F84\u5B50\u5973");
3226
3593
  }
3227
- if (level === 3) {
3228
- return pick2(sex, "\u4F84\u5B59", "\u4F84\u5B59\u5973", "\u4F84\u5B59\u5B50\u5973");
3594
+ if (level === 2) {
3595
+ return pick5(sex, "\u4F84\u5B59", "\u4F84\u5B59\u5973", "\u4F84\u5B59\u5B50\u5973");
3229
3596
  }
3230
- return pick2(
3597
+ return pick5(
3231
3598
  sex,
3232
- `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50`,
3233
- `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5973`,
3234
- `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50\u5973`
3599
+ `${level - 1}\u4EE3\u4E0B\u7684\u4F84\u5B50`,
3600
+ `${level - 1}\u4EE3\u4E0B\u7684\u4F84\u5973`,
3601
+ `${level - 1}\u4EE3\u4E0B\u7684\u4F84\u5B50\u5973`
3235
3602
  );
3236
3603
  }
3237
3604
  parent() {
3238
3605
  return lineal2(
3239
3606
  Math.abs(this.pathN?.level ?? 0),
3240
- sexOf3(this.personN),
3607
+ sexOf6(this.personN),
3241
3608
  "asc"
3242
3609
  );
3243
3610
  }
3244
3611
  child() {
3245
3612
  return lineal2(
3246
3613
  Math.abs(this.pathN?.level ?? 0),
3247
- sexOf3(this.personN),
3614
+ sexOf6(this.personN),
3248
3615
  "desc"
3249
3616
  );
3250
3617
  }
3251
3618
  sibling() {
3252
- return pick2(sexOf3(this.personN), "\u5144\u5F1F", "\u59D0\u59B9", "\u5144\u5F1F\u59D0\u59B9");
3619
+ return pick5(sexOf6(this.personN), "\u5144\u5F1F", "\u59D0\u59B9", "\u5144\u5F1F\u59D0\u59B9");
3253
3620
  }
3254
3621
  halfBlood(relation) {
3255
3622
  if (!relation || !this.isHalfBlood) {
@@ -3258,14 +3625,14 @@ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3258
3625
  return `\u5F02\u7236\u6BCD\u7684${relation}`;
3259
3626
  }
3260
3627
  spouse() {
3261
- return pick2(sexOf3(this.personN), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3628
+ return pick5(sexOf6(this.personN), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3262
3629
  }
3263
3630
  ofSpouse(relation) {
3264
3631
  if (!relation) {
3265
3632
  return "";
3266
3633
  }
3267
- const spouseType = pick2(
3268
- sexOf3(this.path?.[1].indi),
3634
+ const spouseType = pick5(
3635
+ sexOf6(this.path?.[1].indi),
3269
3636
  "\u4E08\u592B",
3270
3637
  "\u59BB\u5B50",
3271
3638
  "\u914D\u5076"
@@ -3277,7 +3644,7 @@ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3277
3644
  return "";
3278
3645
  }
3279
3646
  const spouse = this.path?.[this.path.length - 1].indi;
3280
- const spouseType = pick2(sexOf3(spouse), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3647
+ const spouseType = pick5(sexOf6(spouse), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3281
3648
  return `${relation}\u7684${spouseType}`;
3282
3649
  }
3283
3650
  of(relation) {
@@ -3313,7 +3680,40 @@ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3313
3680
  if (!relation || !this.pathN?.relation) {
3314
3681
  return relation ?? "";
3315
3682
  }
3316
- return `${this.pathN.relation}${relation}`;
3683
+ if (this.pathN.relation === "step") {
3684
+ if (relation === "\u7236\u4EB2") {
3685
+ return "\u7EE7\u7236";
3686
+ }
3687
+ if (relation === "\u6BCD\u4EB2") {
3688
+ return "\u7EE7\u6BCD";
3689
+ }
3690
+ if (relation === "\u513F\u5B50") {
3691
+ return "\u7EE7\u5B50";
3692
+ }
3693
+ if (relation === "\u5973\u513F") {
3694
+ return "\u7EE7\u5973";
3695
+ }
3696
+ return `\u7EE7${relation}`;
3697
+ }
3698
+ if (this.pathN.relation === "adopted") {
3699
+ if (relation === "\u7236\u4EB2") {
3700
+ return "\u517B\u7236";
3701
+ }
3702
+ if (relation === "\u6BCD\u4EB2") {
3703
+ return "\u517B\u6BCD";
3704
+ }
3705
+ if (relation === "\u513F\u5B50") {
3706
+ return "\u517B\u5B50";
3707
+ }
3708
+ if (relation === "\u5973\u513F") {
3709
+ return "\u517B\u5973";
3710
+ }
3711
+ return `\u517B${relation}`;
3712
+ }
3713
+ if (this.pathN.relation === "foster") {
3714
+ return `\u5BC4\u517B${relation}`;
3715
+ }
3716
+ return relation;
3317
3717
  }
3318
3718
  };
3319
3719
 
@@ -4166,11 +4566,8 @@ var storeCache = {
4166
4566
  getCacheDbs().relativesOnDegreeCache.setItem(value);
4167
4567
  }
4168
4568
  }, 50),
4169
- // profilePictureCache IS persisted to IndexedDB
4569
+ // Image bytes are stored as one IndexedDB record per photo.
4170
4570
  profilePictureCache: debounce((value) => {
4171
- if (value) {
4172
- getCacheDbs().profilePictureCache.setItem(value);
4173
- }
4174
4571
  }, 100)
4175
4572
  };
4176
4573
  var resetRelativesCache = () => {
@@ -4868,65 +5265,23 @@ var isRemoteOrEmbeddedMediaUrl = (path) => {
4868
5265
  }
4869
5266
  return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
4870
5267
  };
4871
- var resolveLocalMediaUrl = async (path) => {
5268
+ var resolveLocalMediaUrl = async (path, context) => {
4872
5269
  if (!path) {
4873
5270
  return void 0;
4874
5271
  }
4875
- if (isRemoteOrEmbeddedMediaUrl(path)) {
5272
+ if (path.startsWith("data:") || path.startsWith("blob:")) {
4876
5273
  return path;
4877
5274
  }
4878
- const resolved = await localMediaResolver?.(path);
4879
- return resolved;
4880
- };
4881
- var implemented = (type, ...args) => {
4882
- };
4883
-
4884
- // src/utils/media-utils.ts
4885
- var getFileExtension = (filename) => {
4886
- if (!filename) {
4887
- return "";
4888
- }
4889
- if (filename.startsWith("data:")) {
4890
- const mime = filename.slice(5).split(";")[0] || "";
4891
- const subtype = (mime.split("/")[1] || "").toLowerCase();
4892
- if (subtype === "jpeg") {
4893
- return "jpg";
4894
- }
4895
- return subtype.split("+")[0] || "";
4896
- }
4897
- const withoutQuery = filename.split(/[?#]/)[0] || filename;
4898
- const match = withoutQuery.match(/\.([^.]+)$/);
4899
- return match ? match[1].toLowerCase() : "";
4900
- };
4901
- var isImageFormat = (format2) => {
4902
- if (!format2) {
4903
- return false;
5275
+ const resolved = await localMediaResolver?.(path, context);
5276
+ if (resolved) {
5277
+ return resolved;
4904
5278
  }
4905
- let normalized = format2.toLowerCase().trim();
4906
- if (normalized.startsWith("data:")) {
4907
- normalized = getFileExtension(normalized);
4908
- } else if (normalized.includes("/")) {
4909
- normalized = normalized.split("/")[1]?.split("+")[0] || "";
4910
- if (normalized === "jpeg") {
4911
- normalized = "jpg";
4912
- }
5279
+ if (/^https?:\/\//i.test(path)) {
5280
+ return path;
4913
5281
  }
4914
- const imageFormats = [
4915
- "jpg",
4916
- "jpeg",
4917
- "png",
4918
- "gif",
4919
- "bmp",
4920
- "webp",
4921
- "svg",
4922
- "tiff",
4923
- "tif"
4924
- ];
4925
- return imageFormats.includes(normalized);
5282
+ return void 0;
4926
5283
  };
4927
- var resolveObjeForm = (obje) => {
4928
- const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
4929
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
5284
+ var implemented = (type, ...args) => {
4930
5285
  };
4931
5286
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
4932
5287
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
@@ -6176,22 +6531,19 @@ var Indi = class extends Common {
6176
6531
  if (objeList) {
6177
6532
  await Promise.all(
6178
6533
  objeList.map(async (objeRef) => {
6179
- const key = objeRef?.id;
6534
+ const key = objeXrefKey(objeRef, 0);
6180
6535
  const obje = objeRef?.standardizeMedia(
6181
6536
  namespace,
6182
6537
  true,
6183
- (ns, iId) => {
6184
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
6185
- }
6538
+ ancestryMediaFileUrl
6186
6539
  );
6187
6540
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
6188
- const media = obje?.RIN?.toValue() || obje?.get("_OID")?.toValue();
6189
- const clone = obje?.get("_CLON._OID")?.toValue();
6190
- const mser = obje?.get("_MSER._LKID")?.toValue();
6541
+ const media = resolveObjeMediaId(obje);
6191
6542
  let url = obje?.get("FILE")?.toValue();
6192
6543
  const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
6544
+ const note = objeNoteValue(obje);
6193
6545
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
6194
- let imgId = clone || mser;
6546
+ let imgId = media;
6195
6547
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
6196
6548
  if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
6197
6549
  return;
@@ -6227,6 +6579,7 @@ var Indi = class extends Common {
6227
6579
  imgId,
6228
6580
  person: this.id,
6229
6581
  title,
6582
+ note,
6230
6583
  url,
6231
6584
  contentType: type,
6232
6585
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -6265,7 +6618,7 @@ var Indi = class extends Common {
6265
6618
  return;
6266
6619
  }
6267
6620
  const obje = o;
6268
- const key = `@O${index}@`;
6621
+ const key = objeXrefKey(obje, index);
6269
6622
  obje.standardizeMedia();
6270
6623
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
6271
6624
  const url = obje?.get("FILE")?.toValue();
@@ -6284,6 +6637,7 @@ var Indi = class extends Common {
6284
6637
  imgId,
6285
6638
  person: this.id,
6286
6639
  title,
6640
+ note: objeNoteValue(obje),
6287
6641
  url,
6288
6642
  contentType: type,
6289
6643
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -6392,7 +6746,7 @@ var Indi = class extends Common {
6392
6746
  if (!obje) {
6393
6747
  return;
6394
6748
  }
6395
- const key = `@O${index}@`;
6749
+ const key = objeXrefKey(obje, index);
6396
6750
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
6397
6751
  const url = obje?.get("FILE")?.toValue();
6398
6752
  const title = obje?.get("TITL")?.toValue() ?? "";
@@ -6409,6 +6763,7 @@ var Indi = class extends Common {
6409
6763
  imgId,
6410
6764
  person: this.id,
6411
6765
  title,
6766
+ note: objeNoteValue(obje),
6412
6767
  url,
6413
6768
  contentType: type,
6414
6769
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -6432,7 +6787,7 @@ var Indi = class extends Common {
6432
6787
  if (!obje) {
6433
6788
  return;
6434
6789
  }
6435
- const key = `@O${index}@`;
6790
+ const key = objeXrefKey(obje, index);
6436
6791
  obje.standardizeMedia();
6437
6792
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
6438
6793
  const url = obje?.get("FILE")?.toValue();
@@ -6449,6 +6804,7 @@ var Indi = class extends Common {
6449
6804
  imgId,
6450
6805
  person: this.id,
6451
6806
  title,
6807
+ note: objeNoteValue(obje),
6452
6808
  url,
6453
6809
  contentType: type,
6454
6810
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -6480,7 +6836,12 @@ var Indi = class extends Common {
6480
6836
  );
6481
6837
  if (cached !== void 0) {
6482
6838
  if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
6483
- const resolvedCached = await resolveLocalMediaUrl(cached.file);
6839
+ const resolvedCached = await resolveLocalMediaUrl(cached.file, {
6840
+ url: cached.file,
6841
+ person: this.id,
6842
+ tree: this.getTreeId?.(),
6843
+ treeName: this.getTreeName?.()
6844
+ });
6484
6845
  if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
6485
6846
  const refreshed = { ...cached, file: resolvedCached };
6486
6847
  profilePictureCache(
@@ -6505,7 +6866,16 @@ var Indi = class extends Common {
6505
6866
  }
6506
6867
  const mediaArray = Object.values(mediaList);
6507
6868
  const toDisplayableProfile = async (media, isPrimary) => {
6508
- const resolvedFile = await resolveLocalMediaUrl(media.url);
6869
+ const resolvedFile = await resolveLocalMediaUrl(media.url, {
6870
+ url: media.url,
6871
+ id: media.id,
6872
+ imgId: media.imgId,
6873
+ key: media.key,
6874
+ contentType: media.contentType,
6875
+ person: media.person || this.id,
6876
+ tree: media.tree || this.getTreeId?.(),
6877
+ treeName: this.getTreeName?.()
6878
+ });
6509
6879
  if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
6510
6880
  return void 0;
6511
6881
  }
@@ -8615,7 +8985,7 @@ var ensureExtensionSchema = (gedcom, extraTags) => {
8615
8985
 
8616
8986
  // package.json
8617
8987
  var package_default = {
8618
- version: "2.1.9"};
8988
+ version: "2.1.12"};
8619
8989
 
8620
8990
  // src/utils/get-product-details.ts
8621
8991
  var getVersion = () => package_default.version;
@@ -8695,16 +9065,26 @@ var Obje = class extends Common {
8695
9065
  if (!this._gedcom) {
8696
9066
  return this;
8697
9067
  }
9068
+ if (typeof this.value === "string" && isId(this.value) && this.refType === "OBJE") {
9069
+ const resolved = this.ref;
9070
+ if (resolved && resolved !== this && typeof resolved.standardizeMedia === "function") {
9071
+ resolved.standardizeMedia(
9072
+ namespace,
9073
+ override,
9074
+ urlGetter,
9075
+ gedcomVersion
9076
+ );
9077
+ return this;
9078
+ }
9079
+ }
8698
9080
  const rin = this?.get("RIN")?.toValue();
8699
- const clone = this?.get("_CLON._OID")?.toValue();
8700
- const mser = this?.get("_MSER._LKID")?.toValue();
8701
9081
  const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
8702
9082
  const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
8703
9083
  const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
8704
9084
  const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
8705
9085
  const file = this?.get("FILE")?.toValue();
8706
- const imgId = rin || clone || mser;
8707
- const url = file || namespace && urlGetter?.(namespace, imgId);
9086
+ const imgId = resolveObjeMediaId(this);
9087
+ const url = file || this.isAncestry() && namespace && urlGetter?.(namespace, imgId);
8708
9088
  if (!url) {
8709
9089
  return this;
8710
9090
  }
@@ -9217,6 +9597,22 @@ var GedCom = class extends Common {
9217
9597
  obje(index) {
9218
9598
  return this.getMain(this.objes(), index);
9219
9599
  }
9600
+ /**
9601
+ * People who link a shared multimedia record (`1 OBJE @On@`), i.e. Ancestry
9602
+ * face tags / everyone the photo is attached to.
9603
+ */
9604
+ indisLinkingObje(objeKey) {
9605
+ const people = [];
9606
+ this.indis()?.forEach((indi) => {
9607
+ const linked = indi?.get("OBJE")?.toList()?.values()?.some(
9608
+ (item) => item?.toValue?.() === objeKey || item?.id === objeKey
9609
+ );
9610
+ if (linked && indi) {
9611
+ people.push(indi);
9612
+ }
9613
+ });
9614
+ return people;
9615
+ }
9220
9616
  sour(index) {
9221
9617
  return this.getMain(this.sours(), index);
9222
9618
  }