| 144 | } |
| 145 | |
| 146 | function extract(options) { |
| 147 | const keys = new Set(); |
| 148 | const patterns = { |
| 149 | default: ['\\b(?:i18n\\(\'|i18n-key=")(\\w+)[\'"]', 1], |
| 150 | json: ['__MSG_(\\w+)__', 1], |
| 151 | }; |
| 152 | const typePatternMap = { |
| 153 | '.js': 'default', |
| 154 | '.json': 'json', |
| 155 | '.html': 'default', |
| 156 | '.vue': 'default', |
| 157 | }; |
| 158 | const locales = new Locales(options); |
| 159 | |
| 160 | function extractFile(data, types) { |
| 161 | if (!Array.isArray(types)) types = [types]; |
| 162 | data = String(data); |
| 163 | types.forEach(function (type) { |
| 164 | const patternData = patterns[type]; |
| 165 | const pattern = new RegExp(patternData[0], 'g'); |
| 166 | const groupId = patternData[1]; |
| 167 | let groups; |
| 168 | while ((groups = pattern.exec(data))) { |
| 169 | keys.add(groups[groupId]); |
| 170 | } |
| 171 | }); |
| 172 | } |
| 173 | |
| 174 | function bufferContents(file, enc, cb) { |
| 175 | if (file.isNull()) return cb(); |
| 176 | if (file.isStream()) return this.emit('error', new PluginError('VM-i18n', 'Stream is not supported.')); |
| 177 | const extname = path.extname(file.path); |
| 178 | const type = typePatternMap[extname]; |
| 179 | if (type) extractFile(file.contents, type); |
| 180 | cb(); |
| 181 | } |
| 182 | |
| 183 | function endStream(cb) { |
| 184 | locales.load() |
| 185 | .then(() => { |
| 186 | keys.forEach(key => { |
| 187 | locales.touch(key); |
| 188 | }); |
| 189 | return locales.dump() |
| 190 | .map(out => new Vinyl({ |
| 191 | path: out.path, |
| 192 | contents: Buffer.from(out.data), |
| 193 | })); |
| 194 | }) |
| 195 | .then(files => { |
| 196 | files.forEach(file => { |
| 197 | this.push(file); |
| 198 | }); |
| 199 | cb(); |
| 200 | }) |
| 201 | .catch(cb); |
| 202 | } |
| 203 | |