@natlibfi/marc-record-validators-melinda 11.3.8 → 11.4.0

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 (39) hide show
  1. package/dist/cyrillux.js +67 -34
  2. package/dist/cyrillux.js.map +1 -1
  3. package/dist/index.js +7 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/translate-terms.js +291 -0
  6. package/dist/translate-terms.js.map +1 -0
  7. package/dist/translate-terms.spec.js +51 -0
  8. package/dist/translate-terms.spec.js.map +1 -0
  9. package/package.json +1 -1
  10. package/src/cyrillux.js +56 -32
  11. package/src/index.js +3 -1
  12. package/src/translate-terms.js +274 -0
  13. package/src/translate-terms.spec.js +52 -0
  14. package/test-fixtures/cyrillux/f01/metadata.json +1 -1
  15. package/test-fixtures/cyrillux/f03/metadata.json +4 -3
  16. package/test-fixtures/cyrillux/f03b/expectedResult.json +21 -0
  17. package/test-fixtures/cyrillux/f03b/metadata.json +11 -0
  18. package/test-fixtures/cyrillux/f03b/record.json +19 -0
  19. package/test-fixtures/cyrillux/f04/metadata.json +4 -3
  20. package/test-fixtures/cyrillux/f08/metadata.json +1 -1
  21. package/test-fixtures/cyrillux/f09/metadata.json +1 -1
  22. package/test-fixtures/cyrillux/f11/expectedResult.json +18 -0
  23. package/test-fixtures/cyrillux/f11/metadata.json +9 -0
  24. package/test-fixtures/cyrillux/f11/record.json +9 -0
  25. package/test-fixtures/cyrillux/f11b/expectedResult.json +18 -0
  26. package/test-fixtures/cyrillux/f11b/metadata.json +9 -0
  27. package/test-fixtures/cyrillux/f11b/record.json +16 -0
  28. package/test-fixtures/translate-terms/01/expectedResult.json +37 -0
  29. package/test-fixtures/translate-terms/01/metadata.json +6 -0
  30. package/test-fixtures/translate-terms/01/record.json +27 -0
  31. package/test-fixtures/translate-terms/02/expectedResult.json +37 -0
  32. package/test-fixtures/translate-terms/02/metadata.json +6 -0
  33. package/test-fixtures/translate-terms/02/record.json +27 -0
  34. package/test-fixtures/translate-terms/03/expectedResult.json +26 -0
  35. package/test-fixtures/translate-terms/03/metadata.json +5 -0
  36. package/test-fixtures/translate-terms/03/record.json +26 -0
  37. package/test-fixtures/translate-terms/04/expectedResult.json +16 -0
  38. package/test-fixtures/translate-terms/04/metadata.json +7 -0
  39. package/test-fixtures/translate-terms/04/record.json +17 -0
@@ -0,0 +1,274 @@
1
+ import clone from 'clone';
2
+ import createDebugLogger from 'debug';
3
+ import {fieldHasSubfield, fieldToString, nvdebug} from './utils';
4
+
5
+
6
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortSubfields');
7
+ const defaultTags = ['648', '650', '651', '655'];
8
+
9
+ const swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};
10
+ const changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};
11
+
12
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-term');
13
+ const termCache = {};
14
+
15
+ // Author(s): Nicholas Volk
16
+ export default function () {
17
+
18
+
19
+ return {
20
+ description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',
21
+ validate, fix
22
+ };
23
+
24
+ async function fix(record) {
25
+ const newFields = await getFields(record, defaultTags, []);
26
+
27
+ newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debug));
28
+
29
+ newFields.forEach(nf => record.insertField(nf));
30
+
31
+ const newFieldsAsStrings = newFields.map(f => fieldToString(f));
32
+
33
+
34
+ return {message: [], fix: newFieldsAsStrings, valid: true};
35
+ }
36
+
37
+ async function validate(record) {
38
+ const newFields = await getFields(record, defaultTags, []);
39
+ if (newFields.length === 0) {
40
+ return {'message': [], 'valid': true};
41
+ }
42
+ const messages = newFields.map(f => fieldToString(f));
43
+
44
+ return {'message': messages, 'valid': false};
45
+ }
46
+
47
+ async function getFields(record, tags, fieldsToAdd) {
48
+ const [currTag, ...remainingTags] = tags;
49
+ if (!currTag) {
50
+ return fieldsToAdd;
51
+ }
52
+ const missingFields = await deriveMissingFields(record, currTag);
53
+
54
+ const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);
55
+ return tmp;
56
+ }
57
+
58
+ function getPairlessFinnishAndSwedishFields(record, tag) {
59
+ const expectedLex = mapTagToLex(tag);
60
+ if (!expectedLex) {
61
+ return [];
62
+ }
63
+ const fields = record.get(tag);
64
+ const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));
65
+ const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));
66
+ const finnishOnly = getMisses(finnishFields, swedishFields);
67
+ const swedishOnly = getMisses(swedishFields, finnishFields);
68
+
69
+ //console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console
70
+ return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));
71
+
72
+ function tagAndFieldAgree(field) {
73
+ // Check that tag and $2 value are pairable:
74
+ const lexData = getLexiconAndLanguage(field); // $2 data
75
+ return expectedLex === lexData.lex;
76
+ }
77
+ }
78
+
79
+ async function deriveMissingFields(record, tag) {
80
+ const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);
81
+
82
+ /* eslint-disable */
83
+ // Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)
84
+ let prefLabels = [];
85
+ for (let i=0; i < pairlessFields.length; i += 1) {
86
+ prefLabels[i] = await getPrefLabel(pairlessFields[i]);
87
+ }
88
+ /* eslint-enable */
89
+
90
+ const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));
91
+ return missingFields.filter(f => f);
92
+ }
93
+
94
+ function pairField(field, prefLabels) {
95
+ if (!prefLabels) {
96
+ return undefined;
97
+ }
98
+ //console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console
99
+ const lexAndLang = getLexiconAndLanguage(field);
100
+ //console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console
101
+ const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));
102
+ const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);
103
+ //console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console
104
+ const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');
105
+ const sf0 = clone(field.subfields.find(sf => sf.code === '0'));
106
+ const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe
107
+ const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};
108
+ return newField;
109
+ }
110
+
111
+ function getLexiconAndLanguage(field) {
112
+ const subfield2 = field.subfields.find(sf => sf.code === '2');
113
+ if (subfield2.value === 'slm/fin') {
114
+ return {'lex': 'slm', 'lang': 'fin'};
115
+ }
116
+ if (subfield2.value === 'slm/swe') {
117
+ return {'lex': 'slm', 'lang': 'swe'};
118
+ }
119
+ if (subfield2.value === 'yso/fin') {
120
+ return {'lex': 'yso', 'lang': 'fin'};
121
+ }
122
+ if (subfield2.value === 'yso/swe') {
123
+ return {'lex': 'yso', 'lang': 'swe'};
124
+ }
125
+ return {};
126
+ }
127
+
128
+ async function getPrefLabel(field) {
129
+ // Tag vs $2 correlation has already been checked!
130
+ const uri = fieldToUri(field);
131
+ if (!uri) { // $0 is invalid or sumthing
132
+ return undefined;
133
+ }
134
+ const prefLabels = await getTermData(uri);
135
+ if (!prefLabels) { // Sanity check. Miss caused by illegal id etc.
136
+ nvdebug(`No labels found for ${uri}`, debug);
137
+ return undefined;
138
+ }
139
+ const lexData = getLexiconAndLanguage(field); // $2 data
140
+ const lang = changeAbbr(lexData.lang);
141
+
142
+
143
+ const subfieldA = field.subfields.find(sf => sf.code === 'a');
144
+
145
+ const prefLabel = prefLabels.find(pl => pl.lang === lang);
146
+ //console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console
147
+ if (prefLabel.value === subfieldA.value) {
148
+ nvdebug(`'${fieldToString(field)}' requires translating`, debug);
149
+ return prefLabels;
150
+ }
151
+ return undefined;
152
+ }
153
+
154
+ function swapLanguageCodeBetweenLanguages(code) {
155
+ if (swapLanguageCode[code]) {
156
+ return swapLanguageCode[code];
157
+ }
158
+ return code;
159
+ }
160
+
161
+ function changeAbbr(abbr) {
162
+ if (changeAbbrHash[abbr]) {
163
+ return changeAbbrHash[abbr];
164
+ }
165
+ return abbr;
166
+ }
167
+
168
+ function swaggerQuery(uri) {
169
+ // This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;
170
+ return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data
171
+ }
172
+
173
+ async function getTermData(uri) {
174
+ //console.log(`getTermData(${uri})`); // eslint-disable-line no-console
175
+ if (termCache[uri]) { // Don't think current implementation uses the cache any more.
176
+ //console.log(`CACHED ${uri}`); // eslint-disable-line no-console
177
+ return termCache[uri];
178
+ }
179
+ const tmp = await getTermDataFromFinto(uri);
180
+ termCache[uri] = tmp; // eslint-disable-line functional/immutable-data, require-atomic-updates
181
+ return tmp;
182
+ }
183
+
184
+ async function getTermDataFromFinto(uri) {
185
+ const headers = {'Accept': 'application/json'};
186
+ const uri2 = swaggerQuery(uri);
187
+
188
+ const response = await fetch(uri2, {method: 'GET', headers});
189
+ if (!response.ok) {
190
+ return undefined;
191
+ }
192
+ const json = await response.json();
193
+
194
+ if (!json.graph) {
195
+ return undefined;
196
+ }
197
+ const arr = json.graph;
198
+ const [hit] = arr.filter(row => row.uri === uri);
199
+ //console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console
200
+ return hit.prefLabel;
201
+ }
202
+
203
+
204
+ function fieldToUri(field) {
205
+ const lex = mapTagToLex(field.tag);
206
+
207
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
208
+ const id = subfield0.value.replace(/^[^0-9]+/u, '');
209
+ if (lex === 'yso') {
210
+ //return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;
211
+ return `http://www.yso.fi/onto/yso/p${id}`;
212
+ }
213
+ if (lex === 'slm') {
214
+ return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
215
+ }
216
+ return undefined;
217
+ }
218
+
219
+ function isRelevantField(field, lang) {
220
+ const fieldAsString = fieldToString(field);
221
+
222
+ // We should probably allow an optional $8 as the first subfield.
223
+ if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
224
+ return false;
225
+ }
226
+ const lex = mapTagToLex(field.tag);
227
+ const lexLang = `${lex}/${lang}`;
228
+ if (!fieldHasSubfield(field, '2', lexLang)) {
229
+ return false;
230
+ }
231
+ return fieldHasValidSubfield0(field);
232
+ }
233
+
234
+ function fieldHasValidSubfield0(field) {
235
+ const lex = mapTagToLex(field.tag);
236
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
237
+ if (lex === 'yso' && subfield0.value.match(/^http:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
238
+ return true;
239
+ }
240
+ if (lex === 'slm' && subfield0.value.match(/^http:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
241
+ return true;
242
+ }
243
+ return false;
244
+ }
245
+
246
+ function getMisses(fieldList1, fieldList2) {
247
+ return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));
248
+ }
249
+
250
+ function hasSubfield0Match(field, pairFields) {
251
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
252
+ return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));
253
+ }
254
+
255
+
256
+ function mapTagToLex(tag) {
257
+ if (tag === '655') {
258
+ return 'slm';
259
+ }
260
+ return 'yso';
261
+ }
262
+
263
+
264
+ /*
265
+ function getValidIdentifiers(record, tag, lang) {
266
+ const lex = mapTagToLex(tag);
267
+ const subfield2Value = `${lex}/${lang}`;
268
+ const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter
269
+ return [];
270
+ }
271
+ */
272
+
273
+ }
274
+
@@ -0,0 +1,52 @@
1
+ import {expect} from 'chai';
2
+ import {MarcRecord} from '@natlibfi/marc-record';
3
+ import validatorFactory from './translate-terms';
4
+ import {READERS} from '@natlibfi/fixura';
5
+ import generateTests from '@natlibfi/fixugen';
6
+ import createDebugLogger from 'debug';
7
+
8
+ generateTests({
9
+ callback,
10
+ path: [__dirname, '..', 'test-fixtures', 'translate-terms'],
11
+ useMetadataFile: true,
12
+ recurse: false,
13
+ fixura: {
14
+ reader: READERS.JSON
15
+ },
16
+ mocha: {
17
+ before: () => testValidatorFactory()
18
+ }
19
+ });
20
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-terms:test');
21
+
22
+ async function testValidatorFactory() {
23
+ const validator = await validatorFactory();
24
+
25
+ expect(validator)
26
+ .to.be.an('object')
27
+ .that.has.any.keys('description', 'validate');
28
+
29
+ expect(validator.description).to.be.a('string');
30
+ expect(validator.validate).to.be.a('function');
31
+ }
32
+
33
+ async function callback({getFixture, enabled = true, fix = false}) {
34
+ if (enabled === false) {
35
+ debug('TEST SKIPPED!');
36
+ return;
37
+ }
38
+
39
+ const validator = await validatorFactory();
40
+ const record = new MarcRecord(getFixture('record.json'));
41
+ const expectedResult = getFixture('expectedResult.json');
42
+ // console.log(expectedResult); // eslint-disable-line
43
+
44
+ if (!fix) {
45
+ const result = await validator.validate(record);
46
+ expect(result).to.eql(expectedResult);
47
+ return;
48
+ }
49
+
50
+ await validator.fix(record);
51
+ expect(record).to.eql(expectedResult);
52
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Fix: field 100 required translitteration",
2
+ "description": "01 Fix: field 100 required translitteration",
3
3
  "only": false,
4
4
  "fix": true
5
5
  }
@@ -1,10 +1,11 @@
1
1
  {
2
- "description": "Fix: just convert field 100 to ISO-9 latinitsa",
2
+ "description": "03 Fix: just convert field 100 to ISO-9 latinitsa, don't retain the original nor do sfs4900",
3
3
  "comment": "Tests usage of config and omitting of $6 and $9",
4
4
  "only": false,
5
5
  "fix": true,
6
6
  "config": {
7
- "doISO9Transliteration": false,
8
- "doSFS4900Transliteration": false
7
+ "doISO9Transliteration": true,
8
+ "doSFS4900Transliteration": false,
9
+ "retainCyrillic": false
9
10
  }
10
11
  }
@@ -0,0 +1,21 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "leader": "12345cam 22123454i 4500",
4
+ "fields": [
5
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "Modin, Ûrij Ivanovič." }
7
+ ]},
8
+ { "tag": "245", "ind1": "1", "ind2": " ", "subfields": [
9
+ { "code": "a", "value": "Sudʹby razvedčikov." }
10
+ ]},
11
+ {"tag": "500", "ind1": " ", "ind2": " ", "subfields": [
12
+ { "code": "6", "value": "880-01"},
13
+ { "code": "a", "value": "FOO."}
14
+ ]},
15
+ {"tag": "880", "ind1": " ", "ind2": " ", "subfields": [
16
+ { "code": "6", "value": "500-01"},
17
+ { "code": "a", "value": "BAR."}
18
+ ]}
19
+ ]
20
+ }
21
+
@@ -0,0 +1,11 @@
1
+ {
2
+ "description": "03b Fix: just convert field 100 to SFS4900 latinitsa, don't retain the original nor do ISO-9",
3
+ "comment": "Tests usage of config and omitting of $6 and $9",
4
+ "only": false,
5
+ "fix": true,
6
+ "config": {
7
+ "doISO9Transliteration": false,
8
+ "doSFS4900Transliteration": true,
9
+ "retainCyrillic": false
10
+ }
11
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "leader": "12345cam 22123454i 4500",
3
+ "fields": [
4
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
5
+ { "code": "a", "value": "Модин, Юрий Иванович." }
6
+ ]},
7
+ {"tag": "245", "ind1": "1", "ind2": " ", "subfields": [
8
+ { "code": "a", "value": "Судьбы разведчиков."}
9
+ ]},
10
+ {"tag": "500", "ind1": " ", "ind2": " ", "subfields": [
11
+ { "code": "6", "value": "880-01"},
12
+ { "code": "a", "value": "FOO."}
13
+ ]},
14
+ {"tag": "880", "ind1": " ", "ind2": " ", "subfields": [
15
+ { "code": "6", "value": "500-01"},
16
+ { "code": "a", "value": "BAR."}
17
+ ]}
18
+ ]
19
+ }
@@ -1,10 +1,11 @@
1
1
  {
2
- "description": "Fix: just convert field 100 to ISO-9 latinitsa",
2
+ "description": "04 Fix: just convert field 100 to ISO-9 latinitsa",
3
3
  "comment": "Tests usage of config and omitting of $6 and $9",
4
4
  "only": false,
5
5
  "fix": true,
6
6
  "config": {
7
- "doISO9Transliteration": false,
8
- "doSFS4900Transliteration": false
7
+ "doISO9Transliteration": true,
8
+ "doSFS4900Transliteration": false,
9
+ "retainCyrillic": false
9
10
  }
10
11
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Fix MELINDA-10330: fields 100 and 245 are already in SFS-4900 and their only 880 pairs are Cyrillic",
2
+ "description": "08 Fix MELINDA-10330: fields 100 and 245 are already in SFS-4900 and their only 880 pairs are Cyrillic",
3
3
  "comment": "Use 880 to create 100/245 in ISO-9. Move original SFS-4900 to 880, add $9s",
4
4
  "comment #2": "Note that the original punctuation in 100/245 is overwritten with punctuation from paired 880",
5
5
  "only": false,
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Fix MELINDA-10330, round 3: big file that had issues",
2
+ "description": "09 Fix MELINDA-10330, round 3: big file that had issues",
3
3
  "comment": "Some sorting issues: SIDs are sorted by $c (bug) and LOW precedes SID...",
4
4
  "only": false,
5
5
  "fix": true,
@@ -0,0 +1,18 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "leader": "12345cam 22123454i 4500",
4
+ "fields": [
5
+ { "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
6
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
7
+ { "code": "6", "value": "880-01" },
8
+ { "code": "a", "value": "Gogolʹ." },
9
+ { "code": "9", "value": "ISO9 <TRANS>" }
10
+ ]},
11
+ { "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
12
+ { "code": "6", "value": "100-01" },
13
+ { "code": "a", "value": "Гоголь." },
14
+ { "code": "9", "value": "CYRILLIC <TRANS>" }
15
+ ]}
16
+ ]
17
+ }
18
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "description": "03: transliterate (ISO-9 only)",
3
+ "only": false,
4
+ "fix": true,
5
+ "config": {
6
+ "doISO9Transliteration": true,
7
+ "doSFS4900Transliteration": false
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "leader": "12345cam 22123454i 4500",
3
+ "fields": [
4
+ { "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
5
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "Гоголь." }
7
+ ]}
8
+ ]
9
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "leader": "12345cam 22123454i 4500",
4
+ "fields": [
5
+ { "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
6
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
7
+ { "code": "6", "value": "880-01" },
8
+ { "code": "a", "value": "Gogolʹ." },
9
+ { "code": "9", "value": "ISO9 <TRANS>" }
10
+ ]},
11
+ { "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
12
+ { "code": "6", "value": "100-01" },
13
+ { "code": "a", "value": "Гоголь." },
14
+ { "code": "9", "value": "CYRILLIC <TRANS>" }
15
+ ]}
16
+ ]
17
+ }
18
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "description": "f11b: use output from the f11",
3
+ "only": false,
4
+ "fix": true,
5
+ "config": {
6
+ "doISO9Transliteration": true,
7
+ "doSFS4900Transliteration": false
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "leader": "12345cam 22123454i 4500",
3
+ "fields": [
4
+ { "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
5
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
6
+ { "code": "6", "value": "880-01" },
7
+ { "code": "a", "value": "Gogolʹ." },
8
+ { "code": "9", "value": "ISO9 <TRANS>" }
9
+ ]},
10
+ { "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
11
+ { "code": "6", "value": "100-01" },
12
+ { "code": "a", "value": "Гоголь." },
13
+ { "code": "9", "value": "CYRILLIC <TRANS>" }
14
+ ]}
15
+ ]
16
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
5
+ { "code": "a", "value": "laiturit" },
6
+ { "code": "2", "value": "yso/fin" },
7
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
8
+ ]},
9
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
10
+ { "code": "a", "value": "marxismi" },
11
+ { "code": "2", "value": "yso/fin" },
12
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
13
+ ]},
14
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
15
+ { "code": "a", "value": "marxism" },
16
+ { "code": "2", "value": "yso/swe" },
17
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
18
+ ]},
19
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
20
+ { "code": "a", "value": "bryggor" },
21
+ { "code": "2", "value": "yso/swe" },
22
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
23
+ ]},
24
+ { "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
25
+ { "code": "a", "value": "Ivalo (Enare)" },
26
+ { "code": "2", "value": "yso/swe" },
27
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
28
+ ]},
29
+ { "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
30
+ { "code": "a", "value": "Ivalo (Inari)" },
31
+ { "code": "2", "value": "yso/fin" },
32
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
33
+ ]}
34
+
35
+ ],
36
+ "leader": ""
37
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "01: insert one fin->swe and one swe->fin translation",
3
+ "comment": "Fields are inserted in tag order. Inserted fields are not sorted.",
4
+ "fix": true,
5
+ "only": false
6
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "leader": "",
4
+ "fields": [
5
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
6
+ { "code": "a", "value": "laiturit" },
7
+ { "code": "2", "value": "yso/fin" },
8
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
9
+ ]
10
+ },
11
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
12
+ { "code": "a", "value": "marxismi" },
13
+ { "code": "2", "value": "yso/fin" },
14
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
15
+ ]},
16
+ { "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
17
+ { "code": "a", "value": "marxism" },
18
+ { "code": "2", "value": "yso/swe" },
19
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
20
+ ]},
21
+ { "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
22
+ { "code": "a", "value": "Ivalo (Enare)" },
23
+ { "code": "2", "value": "yso/swe" },
24
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
25
+ ]}
26
+ ]
27
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "648", "ind1": " ", "ind2": "7", "subfields": [
5
+ { "code": "a", "value": "1960-luku" },
6
+ { "code": "2", "value": "yso/fin" },
7
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p6196061969" }
8
+ ]
9
+ },
10
+ { "tag": "648", "ind1": " ", "ind2": "7", "subfields": [
11
+ { "code": "a", "value": "1960-talet" },
12
+ { "code": "2", "value": "yso/swe" },
13
+ { "code": "0", "value": "http://www.yso.fi/onto/yso/p6196061969" }
14
+ ]},
15
+ { "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
16
+ { "code": "a", "value": "damtidningar" },
17
+ { "code": "2", "value": "slm/swe" },
18
+ { "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s161" }
19
+ ]},
20
+ { "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
21
+ { "code": "a", "value": "nekrologit" },
22
+ { "code": "2", "value": "slm/fin" },
23
+ { "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s1324" }
24
+ ]},
25
+ { "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
26
+ { "code": "a", "value": "nekrologer" },
27
+ { "code": "2", "value": "slm/swe" },
28
+ { "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s1324" }
29
+ ]},
30
+ { "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
31
+ { "code": "a", "value": "naistenlehdet" },
32
+ { "code": "2", "value": "slm/fin" },
33
+ { "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s161" }
34
+ ]}
35
+ ],
36
+ "leader": ""
37
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "02: insert one fin->swe (yso-aika) and one swe->fin (slm) translation",
3
+ "comment": "Fields are inserted in tag order. Inserted fields are not sorted.",
4
+ "fix": true,
5
+ "only": false
6
+ }