next-intl 4.14.7 → 4.14.8
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.
- package/dist/cjs/development/plugin.cjs +2 -2
- package/dist/esm/development/extractor/catalog/CatalogManager.js +1 -1
- package/dist/esm/development/extractor/utils.js +1 -1
- package/dist/esm/production/extractor/catalog/CatalogManager.js +1 -1
- package/dist/esm/production/extractor/utils.js +1 -1
- package/dist/types/extractor/format/codecs/fixtures/POCodecLegacy.d.ts +2 -0
- package/package.json +7 -7
|
@@ -445,7 +445,7 @@ function localeCompare(a, b) {
|
|
|
445
445
|
function compareReferences(refA, refB) {
|
|
446
446
|
const pathCompare = localeCompare(refA.path, refB.path);
|
|
447
447
|
if (pathCompare !== 0) return pathCompare;
|
|
448
|
-
return (refA.line ?? 0) - (refB.line ?? 0);
|
|
448
|
+
return (refA.line ?? 0) - (refB.line ?? 0) || (refA.column ?? 0) - (refB.column ?? 0);
|
|
449
449
|
}
|
|
450
450
|
function getDefaultProjectRoot() {
|
|
451
451
|
return process.cwd();
|
|
@@ -1018,7 +1018,7 @@ class CatalogManager {
|
|
|
1018
1018
|
return messages1.length === messages2.length && messages1.every((message, index) => this.areSourceMessagesEqual(message, messages2[index]));
|
|
1019
1019
|
}
|
|
1020
1020
|
areSourceMessagesEqual(msg1, msg2) {
|
|
1021
|
-
return msg1.id === msg2.id && msg1.message === msg2.message && msg1.description === msg2.description && msg1.reference.path === msg2.reference.path && msg1.reference.line === msg2.reference.line;
|
|
1021
|
+
return msg1.id === msg2.id && msg1.message === msg2.message && msg1.description === msg2.description && msg1.reference.path === msg2.reference.path && msg1.reference.line === msg2.reference.line && msg1.reference.column === msg2.reference.column;
|
|
1022
1022
|
}
|
|
1023
1023
|
async save() {
|
|
1024
1024
|
return this.saveScheduler.schedule(() => this.saveImpl());
|
|
@@ -335,7 +335,7 @@ class CatalogManager {
|
|
|
335
335
|
return messages1.length === messages2.length && messages1.every((message, index) => this.areSourceMessagesEqual(message, messages2[index]));
|
|
336
336
|
}
|
|
337
337
|
areSourceMessagesEqual(msg1, msg2) {
|
|
338
|
-
return msg1.id === msg2.id && msg1.message === msg2.message && msg1.description === msg2.description && msg1.reference.path === msg2.reference.path && msg1.reference.line === msg2.reference.line;
|
|
338
|
+
return msg1.id === msg2.id && msg1.message === msg2.message && msg1.description === msg2.description && msg1.reference.path === msg2.reference.path && msg1.reference.line === msg2.reference.line && msg1.reference.column === msg2.reference.column;
|
|
339
339
|
}
|
|
340
340
|
async save() {
|
|
341
341
|
return this.saveScheduler.schedule(() => this.saveImpl());
|
|
@@ -51,7 +51,7 @@ function localeCompare(a, b) {
|
|
|
51
51
|
function compareReferences(refA, refB) {
|
|
52
52
|
const pathCompare = localeCompare(refA.path, refB.path);
|
|
53
53
|
if (pathCompare !== 0) return pathCompare;
|
|
54
|
-
return (refA.line ?? 0) - (refB.line ?? 0);
|
|
54
|
+
return (refA.line ?? 0) - (refB.line ?? 0) || (refA.column ?? 0) - (refB.column ?? 0);
|
|
55
55
|
}
|
|
56
56
|
function getDefaultProjectRoot() {
|
|
57
57
|
return process.cwd();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"fs/promises";import s from"path";import{resolveCodec as t,getFormatExtension as a}from"../format/index.js";import o from"../source/SourceFileScanner.js";import r from"../source/SourceFileWatcher.js";import{getDefaultProjectRoot as i,localeCompare as c,compareReferences as n}from"../utils.js";import l from"./CatalogLocales.js";import h from"./CatalogPersister.js";import g from"./SaveScheduler.js";class d{static extractorOwnedAggregatorKeys=new Set(["description","id","message","references"]);sourceMessagesByFile=new Map;sourceMessagesById=new Map;messagesById=new Map;translationsByTargetLocale=new Map;lastWriteByLocale=new Map;constructor(e,s){this.config=e,this.saveScheduler=new g(s.saveDebounceMs??50),this.projectRoot=s.projectRoot??i(),this.isDevelopment=s.isDevelopment??!1,this.extractor=s.extractor,this.isDevelopment&&(this.sourceWatcher=new r(this.getSrcPaths(),this.handleFileEvents.bind(this)),this.sourceWatcher.start())}async getCodec(){return this.codec||(this.codec=await t(this.config.messages.format,this.projectRoot)),this.codec}async getPersister(){return this.persister||(this.persister=new h({messagesPath:this.config.extract.path,codec:await this.getCodec(),extension:a(this.config.messages.format),sourceLocale:this.config.extract.sourceLocale})),this.persister}getCatalogLocales(){if(this.catalogLocales)return this.catalogLocales;{const e=s.join(this.projectRoot,this.config.extract.path);return this.catalogLocales=new l({messagesDir:e,extension:a(this.config.messages.format),locales:this.config.extract.locales,sourceLocale:this.config.extract.sourceLocale}),this.catalogLocales}}async getTargetLocales(){return this.getCatalogLocales().getTargetLocales()}getSrcPaths(){return(Array.isArray(this.config.extract.srcPath)?this.config.extract.srcPath:[this.config.extract.srcPath]).map((e=>s.join(this.projectRoot,e)))}async loadMessages(){const e=await this.loadSourceMessages();if(this.loadCatalogsPromise=this.loadTargetMessages(),await this.loadCatalogsPromise,this.scanCompletePromise=(async()=>{const s=Array.from(await o.getSourceFiles(this.getSrcPaths())).toSorted(c),t=await Promise.all(s.map((async e=>({filePath:e,messages:await this.extractFile(e)}))));for(const{filePath:e,messages:s}of t)s&&this.applyFileMessages(e,s);this.mergeSourceDiskMetadata(e)})(),await this.scanCompletePromise,this.isDevelopment){this.getCatalogLocales().subscribeLocalesChange(this.onLocalesChange)}}async loadSourceMessages(){const e=await this.loadLocaleMessages(this.config.extract.sourceLocale),s=new Map;for(const t of e)s.set(t.id,t);return s}async loadLocaleMessages(e){const s=await this.getPersister(),t=await s.read(e),a=await s.getLastModified(e);return this.lastWriteByLocale.set(e,a),t}async loadTargetMessages(){const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.reloadLocaleCatalog(e))))}async reloadLocaleCatalog(e){const s=await this.loadLocaleMessages(e);if(e===this.config.extract.sourceLocale)for(const e of s){const s=this.messagesById.get(e.id);if(s)for(const t of Object.keys(e))d.extractorOwnedAggregatorKeys.has(t)||(s[t]=e[t])}else{const t=this.translationsByTargetLocale.get(e),a=t&&t.size>0;if(s.length>0){const t=new Map;for(const e of s)t.set(e.id,e);this.translationsByTargetLocale.set(e,t)}else if(a);else{const s=new Map;this.translationsByTargetLocale.set(e,s)}}}mergeSourceDiskMetadata(e){for(const[s,t]of e){const e=this.messagesById.get(s);if(e)for(const s of Object.keys(t))d.extractorOwnedAggregatorKeys.has(s)||null!=e[s]||(e[s]=t[s])}}async processFile(e){const s=await this.extractFile(e);return!!s&&this.applyFileMessages(e,s)}async extractFile(s){let t=[];try{const a=await e.readFile(s,"utf8");let o;try{o=await this.extractor.extract(s,a)}catch{return}t=o.messages}catch(e){if("ENOENT"!==e.code)throw e}return t}applyFileMessages(e,s){const t=this.sourceMessagesByFile.get(e),a=this.groupSourceMessagesById(s),o=new Set([...t?.keys()??[],...a.keys()]);a.size>0?this.sourceMessagesByFile.set(e,a):this.sourceMessagesByFile.delete(e);for(const s of o){const t=this.sourceMessagesById.get(s);t&&(t.delete(e),0===t.size&&this.sourceMessagesById.delete(s));const o=a.get(s);if(o){let t=this.sourceMessagesById.get(s);t||(t=new Map,this.sourceMessagesById.set(s,t)),t.set(e,o)}this.rebuildMessageById(s)}return this.haveMessagesChangedForFile(t,a)}groupSourceMessagesById(e){const s=new Map;for(const t of e){const e=s.get(t.id);e?e.push(t):s.set(t.id,[t])}return s}rebuildMessageById(e){const s=Array.from(this.sourceMessagesById.get(e)?.values()??[]).flat();if(0===s.length)return void this.messagesById.delete(e);const t=this.messagesById.get(e),a={description:this.mergeDescriptions(s),id:e,message:s[0].message,references:s.map((e=>e.reference)).sort(n)};if(t)for(const e of Object.keys(t))d.extractorOwnedAggregatorKeys.has(e)||null!=a[e]||(a[e]=t[e]);this.messagesById.set(e,a)}mergeDescriptions(e){const s=e.toSorted(((e,s)=>n(e.reference,s.reference))),t=[];for(const e of s){const{description:s}=e;null==s||t.includes(s)||t.push(s)}return t}haveMessagesChangedForFile(e,s){if(!e)return s.size>0;if(e.size!==s.size)return!0;for(const[t,a]of e){const e=s.get(t);if(!e)return!0;if(!this.areSourceMessageArraysEqual(a,e))return!0}return!1}areSourceMessageArraysEqual(e,s){return e.length===s.length&&e.every(((e,t)=>this.areSourceMessagesEqual(e,s[t])))}areSourceMessagesEqual(e,s){return e.id===s.id&&e.message===s.message&&e.description===s.description&&e.reference.path===s.reference.path&&e.reference.line===s.reference.line}async save(){return this.saveScheduler.schedule((()=>this.saveImpl()))}async saveImpl(){await this.saveLocale(this.config.extract.sourceLocale);const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.saveLocale(e))))}async saveLocale(e){await this.loadCatalogsPromise;const s=Array.from(this.messagesById.values()),t=await this.getPersister(),a=e===this.config.extract.sourceLocale,o=this.lastWriteByLocale.get(e),r=await t.getLastModified(e);r&&o&&r>o&&await this.reloadLocaleCatalog(e);const i=a?this.messagesById:this.translationsByTargetLocale.get(e),c=s.map((e=>{const s=i?.get(e.id);return{...s,id:e.id,description:e.description,references:e.references,message:a?e.message:s?.message??""}}));await t.write(c,{locale:e,sourceMessagesById:this.messagesById});const n=await t.getLastModified(e);this.lastWriteByLocale.set(e,n)}onLocalesChange=async e=>{this.loadCatalogsPromise=Promise.all([this.loadCatalogsPromise,...e.added.map((e=>this.reloadLocaleCatalog(e)))]);for(const s of e.added)await this.saveLocale(s);for(const s of e.removed)this.translationsByTargetLocale.delete(s),this.lastWriteByLocale.delete(s)};async handleFileEvents(e){this.loadCatalogsPromise&&await this.loadCatalogsPromise,this.scanCompletePromise&&await this.scanCompletePromise;let s=!1;const t=await this.sourceWatcher.expandDirectoryDeleteEvents(e,Array.from(this.sourceMessagesByFile.keys()));for(const e of t.toSorted(((e,s)=>c(e.path,s.path)))){const t=await this.processFile(e.path);s||=t}s&&await this.save()}[Symbol.dispose](){this.sourceWatcher?.stop(),this.sourceWatcher=void 0,this.saveScheduler[Symbol.dispose](),this.catalogLocales&&this.isDevelopment&&this.catalogLocales.unsubscribeLocalesChange(this.onLocalesChange)}}export{d as default};
|
|
1
|
+
import e from"fs/promises";import s from"path";import{resolveCodec as t,getFormatExtension as a}from"../format/index.js";import o from"../source/SourceFileScanner.js";import r from"../source/SourceFileWatcher.js";import{getDefaultProjectRoot as i,localeCompare as c,compareReferences as n}from"../utils.js";import l from"./CatalogLocales.js";import h from"./CatalogPersister.js";import g from"./SaveScheduler.js";class d{static extractorOwnedAggregatorKeys=new Set(["description","id","message","references"]);sourceMessagesByFile=new Map;sourceMessagesById=new Map;messagesById=new Map;translationsByTargetLocale=new Map;lastWriteByLocale=new Map;constructor(e,s){this.config=e,this.saveScheduler=new g(s.saveDebounceMs??50),this.projectRoot=s.projectRoot??i(),this.isDevelopment=s.isDevelopment??!1,this.extractor=s.extractor,this.isDevelopment&&(this.sourceWatcher=new r(this.getSrcPaths(),this.handleFileEvents.bind(this)),this.sourceWatcher.start())}async getCodec(){return this.codec||(this.codec=await t(this.config.messages.format,this.projectRoot)),this.codec}async getPersister(){return this.persister||(this.persister=new h({messagesPath:this.config.extract.path,codec:await this.getCodec(),extension:a(this.config.messages.format),sourceLocale:this.config.extract.sourceLocale})),this.persister}getCatalogLocales(){if(this.catalogLocales)return this.catalogLocales;{const e=s.join(this.projectRoot,this.config.extract.path);return this.catalogLocales=new l({messagesDir:e,extension:a(this.config.messages.format),locales:this.config.extract.locales,sourceLocale:this.config.extract.sourceLocale}),this.catalogLocales}}async getTargetLocales(){return this.getCatalogLocales().getTargetLocales()}getSrcPaths(){return(Array.isArray(this.config.extract.srcPath)?this.config.extract.srcPath:[this.config.extract.srcPath]).map((e=>s.join(this.projectRoot,e)))}async loadMessages(){const e=await this.loadSourceMessages();if(this.loadCatalogsPromise=this.loadTargetMessages(),await this.loadCatalogsPromise,this.scanCompletePromise=(async()=>{const s=Array.from(await o.getSourceFiles(this.getSrcPaths())).toSorted(c),t=await Promise.all(s.map((async e=>({filePath:e,messages:await this.extractFile(e)}))));for(const{filePath:e,messages:s}of t)s&&this.applyFileMessages(e,s);this.mergeSourceDiskMetadata(e)})(),await this.scanCompletePromise,this.isDevelopment){this.getCatalogLocales().subscribeLocalesChange(this.onLocalesChange)}}async loadSourceMessages(){const e=await this.loadLocaleMessages(this.config.extract.sourceLocale),s=new Map;for(const t of e)s.set(t.id,t);return s}async loadLocaleMessages(e){const s=await this.getPersister(),t=await s.read(e),a=await s.getLastModified(e);return this.lastWriteByLocale.set(e,a),t}async loadTargetMessages(){const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.reloadLocaleCatalog(e))))}async reloadLocaleCatalog(e){const s=await this.loadLocaleMessages(e);if(e===this.config.extract.sourceLocale)for(const e of s){const s=this.messagesById.get(e.id);if(s)for(const t of Object.keys(e))d.extractorOwnedAggregatorKeys.has(t)||(s[t]=e[t])}else{const t=this.translationsByTargetLocale.get(e),a=t&&t.size>0;if(s.length>0){const t=new Map;for(const e of s)t.set(e.id,e);this.translationsByTargetLocale.set(e,t)}else if(a);else{const s=new Map;this.translationsByTargetLocale.set(e,s)}}}mergeSourceDiskMetadata(e){for(const[s,t]of e){const e=this.messagesById.get(s);if(e)for(const s of Object.keys(t))d.extractorOwnedAggregatorKeys.has(s)||null!=e[s]||(e[s]=t[s])}}async processFile(e){const s=await this.extractFile(e);return!!s&&this.applyFileMessages(e,s)}async extractFile(s){let t=[];try{const a=await e.readFile(s,"utf8");let o;try{o=await this.extractor.extract(s,a)}catch{return}t=o.messages}catch(e){if("ENOENT"!==e.code)throw e}return t}applyFileMessages(e,s){const t=this.sourceMessagesByFile.get(e),a=this.groupSourceMessagesById(s),o=new Set([...t?.keys()??[],...a.keys()]);a.size>0?this.sourceMessagesByFile.set(e,a):this.sourceMessagesByFile.delete(e);for(const s of o){const t=this.sourceMessagesById.get(s);t&&(t.delete(e),0===t.size&&this.sourceMessagesById.delete(s));const o=a.get(s);if(o){let t=this.sourceMessagesById.get(s);t||(t=new Map,this.sourceMessagesById.set(s,t)),t.set(e,o)}this.rebuildMessageById(s)}return this.haveMessagesChangedForFile(t,a)}groupSourceMessagesById(e){const s=new Map;for(const t of e){const e=s.get(t.id);e?e.push(t):s.set(t.id,[t])}return s}rebuildMessageById(e){const s=Array.from(this.sourceMessagesById.get(e)?.values()??[]).flat();if(0===s.length)return void this.messagesById.delete(e);const t=this.messagesById.get(e),a={description:this.mergeDescriptions(s),id:e,message:s[0].message,references:s.map((e=>e.reference)).sort(n)};if(t)for(const e of Object.keys(t))d.extractorOwnedAggregatorKeys.has(e)||null!=a[e]||(a[e]=t[e]);this.messagesById.set(e,a)}mergeDescriptions(e){const s=e.toSorted(((e,s)=>n(e.reference,s.reference))),t=[];for(const e of s){const{description:s}=e;null==s||t.includes(s)||t.push(s)}return t}haveMessagesChangedForFile(e,s){if(!e)return s.size>0;if(e.size!==s.size)return!0;for(const[t,a]of e){const e=s.get(t);if(!e)return!0;if(!this.areSourceMessageArraysEqual(a,e))return!0}return!1}areSourceMessageArraysEqual(e,s){return e.length===s.length&&e.every(((e,t)=>this.areSourceMessagesEqual(e,s[t])))}areSourceMessagesEqual(e,s){return e.id===s.id&&e.message===s.message&&e.description===s.description&&e.reference.path===s.reference.path&&e.reference.line===s.reference.line&&e.reference.column===s.reference.column}async save(){return this.saveScheduler.schedule((()=>this.saveImpl()))}async saveImpl(){await this.saveLocale(this.config.extract.sourceLocale);const e=await this.getTargetLocales();await Promise.all(e.map((e=>this.saveLocale(e))))}async saveLocale(e){await this.loadCatalogsPromise;const s=Array.from(this.messagesById.values()),t=await this.getPersister(),a=e===this.config.extract.sourceLocale,o=this.lastWriteByLocale.get(e),r=await t.getLastModified(e);r&&o&&r>o&&await this.reloadLocaleCatalog(e);const i=a?this.messagesById:this.translationsByTargetLocale.get(e),c=s.map((e=>{const s=i?.get(e.id);return{...s,id:e.id,description:e.description,references:e.references,message:a?e.message:s?.message??""}}));await t.write(c,{locale:e,sourceMessagesById:this.messagesById});const n=await t.getLastModified(e);this.lastWriteByLocale.set(e,n)}onLocalesChange=async e=>{this.loadCatalogsPromise=Promise.all([this.loadCatalogsPromise,...e.added.map((e=>this.reloadLocaleCatalog(e)))]);for(const s of e.added)await this.saveLocale(s);for(const s of e.removed)this.translationsByTargetLocale.delete(s),this.lastWriteByLocale.delete(s)};async handleFileEvents(e){this.loadCatalogsPromise&&await this.loadCatalogsPromise,this.scanCompletePromise&&await this.scanCompletePromise;let s=!1;const t=await this.sourceWatcher.expandDirectoryDeleteEvents(e,Array.from(this.sourceMessagesByFile.keys()));for(const e of t.toSorted(((e,s)=>c(e.path,s.path)))){const t=await this.processFile(e.path);s||=t}s&&await this.save()}[Symbol.dispose](){this.sourceWatcher?.stop(),this.sourceWatcher=void 0,this.saveScheduler[Symbol.dispose](),this.catalogLocales&&this.isDevelopment&&this.catalogLocales.unsubscribeLocalesChange(this.onLocalesChange)}}export{d as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"path";import{warn as
|
|
1
|
+
import t from"path";import{warn as n}from"../plugin/utils.js";function e(n){return t.posix.normalize(n.split(t.win32.sep).join(t.posix.sep))}const o=new Set(["__proto__","constructor","prototype"]);function r(t){return o.has(t)}function c(t){const{locales:n}=t.extract;return"infer"===n||n.length>0}function i(t,n,e){const o=n.split(".");for(const t of o)if(r(t))throw new Error(`Invalid message id segment: ${t}`);let c=t;for(let t=0;t<o.length-1;t++){const n=o[t];Object.prototype.hasOwnProperty.call(c,n)&&"object"==typeof c[n]&&null!==c[n]||(c[n]=Object.create(null)),c=c[n]}c[o[o.length-1]]=e}function s(t){const e=new Set;for(const o of t)null!=o.references[0]||e.has(o.id)||(e.add(o.id),n(`Missing file reference for extracted message: ${o.id}`))}function l(t,n){return t.localeCompare(n,"en")}function f(t,n){const e=l(t.path,n.path);return 0!==e?e:(t.line??0)-(n.line??0)||(t.column??0)-(n.column??0)}function p(){return process.cwd()}export{f as compareReferences,p as getDefaultProjectRoot,c as hasLocalesToExtract,r as isForbiddenObjectKey,l as localeCompare,e as normalizePathToPosix,i as setNestedProperty,s as warnAboutMissingReferences};
|
|
@@ -7,6 +7,7 @@ declare const _default: () => {
|
|
|
7
7
|
references: Array<{
|
|
8
8
|
path: string;
|
|
9
9
|
line?: number;
|
|
10
|
+
column?: number;
|
|
10
11
|
}>;
|
|
11
12
|
segments?: Array<string | number>;
|
|
12
13
|
verbatim?: {
|
|
@@ -23,6 +24,7 @@ declare const _default: () => {
|
|
|
23
24
|
references: Array<{
|
|
24
25
|
path: string;
|
|
25
26
|
line?: number;
|
|
27
|
+
column?: number;
|
|
26
28
|
}>;
|
|
27
29
|
segments?: Array<string | number>;
|
|
28
30
|
verbatim?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-intl",
|
|
3
|
-
"version": "4.14.
|
|
3
|
+
"version": "4.14.8",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"author": "Jan Amann <jan@amann.work>",
|
|
6
6
|
"funding": [
|
|
@@ -124,16 +124,16 @@
|
|
|
124
124
|
"next.js"
|
|
125
125
|
],
|
|
126
126
|
"dependencies": {
|
|
127
|
-
"@eloqnt/config": "^0.1.
|
|
127
|
+
"@eloqnt/config": "^0.1.1",
|
|
128
128
|
"@eloqnt/format-json": "^0.1.0",
|
|
129
|
-
"@eloqnt/format-po": "^0.1.
|
|
129
|
+
"@eloqnt/format-po": "^0.1.1",
|
|
130
130
|
"@formatjs/intl-localematcher": "^0.8.1",
|
|
131
131
|
"@parcel/watcher": "^2.4.1",
|
|
132
132
|
"@swc/core": "~1.16.0",
|
|
133
|
-
"icu-minify": "^4.14.
|
|
133
|
+
"icu-minify": "^4.14.8",
|
|
134
134
|
"negotiator": "^1.0.0",
|
|
135
|
-
"next-intl-swc-plugin-extractor": "4.14.
|
|
136
|
-
"use-intl": "^4.14.
|
|
135
|
+
"next-intl-swc-plugin-extractor": "4.14.8",
|
|
136
|
+
"use-intl": "^4.14.8"
|
|
137
137
|
},
|
|
138
138
|
"peerDependencies": {
|
|
139
139
|
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
@@ -145,5 +145,5 @@
|
|
|
145
145
|
"optional": true
|
|
146
146
|
}
|
|
147
147
|
},
|
|
148
|
-
"gitHead": "
|
|
148
|
+
"gitHead": "274867fbf1a11fd8f1cee6d55f74cc7f0ac1727e"
|
|
149
149
|
}
|