Files
netshift/fe-app-netshift/generate-pot.js
yandexru45 897b93664b rebrand: podkop -> NetShift (v0.8.0) with migration
Full project rebrand to reduce association with upstream podkop, per
upstream maintainers' request.

Renames (git mv, history preserved):
- package podkop -> netshift (/usr/bin/netshift, /etc/config/netshift,
  /etc/init.d/netshift, /etc/netshift state dir, /usr/lib/netshift)
- luci-app-podkop -> luci-app-netshift; view namespace view/podkop -> view/netshift
- fe-app-podkop -> fe-app-netshift; TS namespace Podkop -> NetShift
- nft table PodkopTable -> NetShiftTable; rt_table podkop -> netshift
- nft sets, dnsmasq backup keys, cron self-calls, PID/tmp paths
- i18n podkop.pot/po -> netshift.pot/po; web title Podkop -> NetShift
- build-arg PODKOP_VERSION -> NETSHIFT_VERSION; Dockerfiles + CI workflows

Migration (install.sh migrate_from_podkop): on detecting an old podkop
install, stops the old service (clean teardown of nft/dnsmasq/rt_tables),
copies /etc/config/podkop -> /etc/config/netshift (backup at
/etc/config/podkop.bak.pre-netshift), migrates state dir, strips old
cron/rt_tables entries, removes old packages, then installs NetShift.
Config schema is compatible so the VPN keeps working after migration.

Docs: README + TRADEMARK rewritten for NetShift.

Intentionally kept: upstream attribution (itdoginfo/podkop), podkop.net
docs links, *.podkop.fyi check domains, yandexru45/podkop-evolution repo
URL (GitHub repo not renamed yet), maintainer email.

Verified: bash -n clean, yarn lint/test (283) pass, main.js idempotent,
Docker ipk build produces netshift_v0.8.0 / luci-app-netshift_v0.8.0.
2026-06-02 17:34:44 +03:00

74 lines
2.4 KiB
JavaScript

import fs from 'fs/promises';
import { execSync } from 'child_process';
const inputFile = 'locales/calls.json';
const outputFile = 'locales/netshift.pot';
const projectId = 'NETSHIFT';
function getGitUser() {
const name = execSync('git config user.name').toString().trim();
const email = execSync('git config user.email').toString().trim();
return { name, email };
}
function getPotHeader({ name, email }) {
const now = new Date();
const date = now.toISOString().replace('T', ' ').slice(0, 16);
const offset = -now.getTimezoneOffset();
const sign = offset >= 0 ? '+' : '-';
const hours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0');
const minutes = String(Math.abs(offset) % 60).padStart(2, '0');
const timezone = `${sign}${hours}${minutes}`;
return [
'# SOME DESCRIPTIVE TITLE.',
`# Copyright (C) ${now.getFullYear()} THE PACKAGE'S COPYRIGHT HOLDER`,
`# This file is distributed under the same license as the ${projectId} package.`,
`# ${name} <${email}>, ${now.getFullYear()}.`,
'#, fuzzy',
'msgid ""',
'msgstr ""',
`"Project-Id-Version: ${projectId}\\n"`,
`"Report-Msgid-Bugs-To: \\n"`,
`"POT-Creation-Date: ${date}${timezone}\\n"`,
`"PO-Revision-Date: ${date}${timezone}\\n"`,
`"Last-Translator: ${name} <${email}>\\n"`,
`"Language-Team: LANGUAGE <LL@li.org>\\n"`,
`"Language: \\n"`,
`"MIME-Version: 1.0\\n"`,
`"Content-Type: text/plain; charset=UTF-8\\n"`,
`"Content-Transfer-Encoding: 8bit\\n"`,
'',
].join('\n');
}
function escapePoString(str) {
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
function generateEntry(item) {
const locations = item.places.map(loc => `#: ${loc}`).join('\n');
const msgid = escapePoString(item.key);
return [
locations,
`msgid "${msgid}"`,
`msgstr ""`,
''
].join('\n');
}
async function generatePot() {
const gitUser = getGitUser();
const raw = await fs.readFile(inputFile, 'utf8');
const entries = JSON.parse(raw);
const header = getPotHeader(gitUser);
const body = entries.map(generateEntry).join('\n');
await fs.writeFile(outputFile, `${header}\n${body}`, 'utf8');
console.log(`✅ POT-файл успешно создан: ${outputFile}`);
}
generatePot().catch(console.error);