mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-25 16:11:54 +08:00
fix(update): 按语言加载三语更新日志并重发 v1.0.8
This commit is contained in:
@@ -40,16 +40,26 @@ jobs:
|
||||
- name: Validate archived release notes
|
||||
run: |
|
||||
VERSION="${{ github.ref_name }}"
|
||||
NOTES_FILE="docs/releases/${VERSION}.md"
|
||||
if [ ! -s "$NOTES_FILE" ]; then
|
||||
echo "::error::缺少版本归档 $NOTES_FILE。请在打 tag 前运行 ./Scripts/generate-release-notes.sh $VERSION 并提交。"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -Fq "# ${VERSION}" "$NOTES_FILE"; then
|
||||
echo "::error::$NOTES_FILE 的标题必须包含 # ${VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
cp "$NOTES_FILE" /tmp/release_notes.md
|
||||
for NOTES_FILE in \
|
||||
"docs/releases/${VERSION}.en.md" \
|
||||
"docs/releases/${VERSION}.md" \
|
||||
"docs/releases/${VERSION}.zh-Hant.md"; do
|
||||
if [ ! -s "$NOTES_FILE" ]; then
|
||||
echo "::error::Missing localized release notes: $NOTES_FILE"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -Fq "# ${VERSION}" "$NOTES_FILE"; then
|
||||
echo "::error::$NOTES_FILE must contain the # ${VERSION} heading"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
{
|
||||
cat "docs/releases/${VERSION}.en.md"
|
||||
printf '\n---\n\n'
|
||||
cat "docs/releases/${VERSION}.md"
|
||||
printf '\n---\n\n'
|
||||
cat "docs/releases/${VERSION}.zh-Hant.md"
|
||||
} > /tmp/release_notes.md
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
@@ -15,7 +15,7 @@ responses in a controlled test environment.
|
||||
[](project.yml)
|
||||
[](project.yml)
|
||||
[](Core/go.mod)
|
||||
[](docs/CHANGELOG.md)
|
||||
[](docs/CHANGELOG.en.md)
|
||||
|
||||
[Features](#feature-overview) ·
|
||||
[How It Works](#how-it-works) ·
|
||||
@@ -415,7 +415,7 @@ Paste it into the **App-generated diagnostic report** field in the GitHub Issue
|
||||
|
||||
- [Build guide](docs/BUILD.md)
|
||||
- [Third-party module documentation](docs/THIRD_PARTY_MODULES.md)
|
||||
- [Changelog](docs/CHANGELOG.md)
|
||||
- [Changelog](docs/CHANGELOG.en.md)
|
||||
- [中文文档](README.zh-CN.md)
|
||||
- [GitHub Issues](https://github.com/xweiba/location-spoofer/issues)
|
||||
|
||||
|
||||
@@ -49,3 +49,4 @@ ${COMMITS}
|
||||
EOF
|
||||
|
||||
echo "Generated $OUTPUT from $RANGE"
|
||||
echo "Before tagging, add docs/releases/${VERSION}.en.md and docs/releases/${VERSION}.zh-Hant.md."
|
||||
|
||||
@@ -153,11 +153,13 @@ enum AppRemoteConfigurationService {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func fetchReleaseNotes(version: String) async -> String? {
|
||||
static func fetchReleaseNotes(
|
||||
version: String, language: String = AppLocalization.identifier
|
||||
) async -> String? {
|
||||
let session = makeSession()
|
||||
defer { session.finishTasksAndInvalidate() }
|
||||
|
||||
for url in releaseNotesURLs(version: version) {
|
||||
for url in releaseNotesURLs(version: version, language: language) {
|
||||
var request = URLRequest(url: url)
|
||||
request.timeoutInterval = 1.5
|
||||
|
||||
@@ -166,7 +168,7 @@ enum AppRemoteConfigurationService {
|
||||
guard let httpResponse = response as? HTTPURLResponse,
|
||||
httpResponse.statusCode == 200,
|
||||
let markdown = String(data: data, encoding: .utf8),
|
||||
let summary = releaseNotesSummary(markdown) else {
|
||||
let summary = releaseNotesSummary(markdown, language: language) else {
|
||||
continue
|
||||
}
|
||||
return summary
|
||||
@@ -185,8 +187,17 @@ enum AppRemoteConfigurationService {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func releaseNotesURLs(version: String) -> [URL] {
|
||||
let path = "https://raw.githubusercontent.com/xweiba/location-spoofer/main/docs/releases/v\(version).md"
|
||||
static func releaseNotesURLs(
|
||||
version: String, language: String = AppLocalization.identifier
|
||||
) -> [URL] {
|
||||
// The unsuffixed archive remains Simplified Chinese for older clients.
|
||||
let suffix: String
|
||||
switch language {
|
||||
case "zh-Hans": suffix = ""
|
||||
case "zh-Hant": suffix = ".zh-Hant"
|
||||
default: suffix = ".en"
|
||||
}
|
||||
let path = "https://raw.githubusercontent.com/xweiba/location-spoofer/main/docs/releases/v\(version)\(suffix).md"
|
||||
return [
|
||||
URL(string: "https://gh-proxy.org/\(path)")!,
|
||||
URL(string: path)!
|
||||
@@ -202,12 +213,14 @@ enum AppRemoteConfigurationService {
|
||||
return URLSession(configuration: sessionConfiguration)
|
||||
}
|
||||
|
||||
private static func releaseNotesSummary(_ markdown: String) -> String? {
|
||||
static func releaseNotesSummary(_ markdown: String, language: String) -> String? {
|
||||
var items: [String] = []
|
||||
var inMainUpdates = false
|
||||
for rawLine in markdown.components(separatedBy: .newlines) {
|
||||
let line = rawLine.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if line == "## 主要更新" {
|
||||
let heading = language == "zh-Hans" || language == "zh-Hant"
|
||||
? "## 主要更新" : "## Highlights"
|
||||
if line == heading {
|
||||
inMainUpdates = true
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -77,8 +77,44 @@ final class AppRemoteConfigurationTests: XCTestCase {
|
||||
"raw.githubusercontent.com"
|
||||
)
|
||||
|
||||
let releaseNotesURLs = AppRemoteConfigurationService.releaseNotesURLs(version: "1.0.5")
|
||||
let releaseNotesURLs = AppRemoteConfigurationService.releaseNotesURLs(version: "1.0.8", language: "en")
|
||||
XCTAssertEqual(releaseNotesURLs.first?.host, "gh-proxy.org")
|
||||
XCTAssertEqual(releaseNotesURLs.last?.host, "raw.githubusercontent.com")
|
||||
XCTAssertTrue(releaseNotesURLs.last?.path.hasSuffix("/docs/releases/v1.0.8.en.md") == true)
|
||||
XCTAssertTrue(AppRemoteConfigurationService.releaseNotesURLs(
|
||||
version: "1.0.8", language: "zh-Hans"
|
||||
).last?.path.hasSuffix("/docs/releases/v1.0.8.md") == true)
|
||||
XCTAssertTrue(AppRemoteConfigurationService.releaseNotesURLs(
|
||||
version: "1.0.8", language: "zh-Hant"
|
||||
).last?.path.hasSuffix("/docs/releases/v1.0.8.zh-Hant.md") == true)
|
||||
XCTAssertTrue(AppRemoteConfigurationService.releaseNotesURLs(
|
||||
version: "1.0.8", language: "it"
|
||||
).last?.path.hasSuffix("/docs/releases/v1.0.8.en.md") == true)
|
||||
}
|
||||
|
||||
func testReleaseNotesSummaryUsesTheSelectedLanguageHeading() {
|
||||
let english = "# v1.0.8\n\n## Highlights\n\n- English update\n\n## Installation"
|
||||
let chinese = "# v1.0.8\n\n## 主要更新\n\n- 中文更新\n\n## 安装"
|
||||
XCTAssertEqual(AppRemoteConfigurationService.releaseNotesSummary(english, language: "en"), "• English update")
|
||||
XCTAssertEqual(AppRemoteConfigurationService.releaseNotesSummary(chinese, language: "zh-Hans"), "• 中文更新")
|
||||
XCTAssertEqual(AppRemoteConfigurationService.releaseNotesSummary(chinese, language: "zh-Hant"), "• 中文更新")
|
||||
XCTAssertNil(AppRemoteConfigurationService.releaseNotesSummary(chinese, language: "en"))
|
||||
XCTAssertEqual(AppRemoteConfigurationService.releaseNotesSummary(english, language: "it"), "• English update")
|
||||
}
|
||||
|
||||
func testArchivedReleaseNotesParseInEachLanguage() throws {
|
||||
let root = URL(fileURLWithPath: #filePath)
|
||||
.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent()
|
||||
for (language, name) in [
|
||||
("en", "v1.0.8.en.md"),
|
||||
("zh-Hans", "v1.0.8.md"),
|
||||
("zh-Hant", "v1.0.8.zh-Hant.md")
|
||||
] {
|
||||
let markdown = try String(
|
||||
contentsOf: root.appendingPathComponent("docs/releases/\(name)"),
|
||||
encoding: .utf8
|
||||
)
|
||||
XCTAssertNotNil(AppRemoteConfigurationService.releaseNotesSummary(markdown, language: language))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,6 @@ grep -q 'presentSuccessfulOperationTip(.activation)' "$ROOT/App/MapHomeView.swif
|
||||
grep -q 'presentSuccessfulOperationTip(.deactivation)' "$ROOT/App/MapHomeView.swift" || fail "third-party clear must present the deactivation tip"
|
||||
grep -q 'if spoofState == .active' "$ROOT/App/MapHomeView.swift" || fail "manual help must follow the shared spoof state"
|
||||
grep -q 'MARKETING_VERSION: "1.0.8"' "$ROOT/project.yml" || fail "marketing version must be 1.0.8"
|
||||
grep -q 'CURRENT_PROJECT_VERSION: "9"' "$ROOT/project.yml" || fail "build version must be 9"
|
||||
grep -q 'CURRENT_PROJECT_VERSION: "10"' "$ROOT/project.yml" || fail "build version must be 10"
|
||||
|
||||
echo "PASS: third-party proxy mode contract"
|
||||
|
||||
@@ -54,8 +54,16 @@ grep -q 'static let configurationURLs = \[' "$CONFIG" \
|
||||
|| fail "update detection must retain multiple configuration sources"
|
||||
! grep -q 'data.count' "$CONFIG" \
|
||||
|| fail "the client must not impose a remote configuration file-size limit"
|
||||
grep -q 'docs/releases/v\\(version).md' "$CONFIG" \
|
||||
|| fail "update notes must come from the archived release document"
|
||||
grep -Fq 'docs/releases/v\(version)\(suffix).md' "$CONFIG" \
|
||||
|| fail "update notes must come from the language-specific archived release document"
|
||||
for locale in '' .en .zh-Hant; do
|
||||
test -s "$ROOT/docs/releases/v${LATEST_VERSION}${locale}.md" \
|
||||
|| fail "missing localized v${LATEST_VERSION}${locale} release notes"
|
||||
done
|
||||
grep -Fq '## Highlights' "$ROOT/docs/releases/v${LATEST_VERSION}.en.md" \
|
||||
|| fail "English update highlights are missing"
|
||||
grep -Fq '## 主要更新' "$ROOT/docs/releases/v${LATEST_VERSION}.zh-Hant.md" \
|
||||
|| fail "Traditional Chinese update highlights are missing"
|
||||
grep -q '/releases/latest' "$CONFIG" \
|
||||
|| fail "missing release notes must fall back to the latest Release page"
|
||||
grep -q '.task { await checkForUpdates() }' "$CONTENT" \
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
Release notes are archived under [`docs/releases/`](releases/).
|
||||
|
||||
## Releases
|
||||
|
||||
- [v1.0.8](releases/v1.0.8.en.md) — September 24, 2026 ([简体中文](releases/v1.0.8.md) · [繁體中文](releases/v1.0.8.zh-Hant.md))
|
||||
- [v1.0.7](releases/v1.0.7.md) — September 11, 2026 (Chinese)
|
||||
- [v1.0.6](releases/v1.0.6.md) — September 1, 2026 (Chinese)
|
||||
|
||||
Earlier releases: [GitHub Releases](https://github.com/xweiba/location-spoofer/releases).
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
各版本发布说明见 `docs/releases/` 目录。
|
||||
|
||||
[English](CHANGELOG.en.md) · [繁體中文](CHANGELOG.zh-Hant.md)
|
||||
|
||||
## 已发布
|
||||
|
||||
- [v1.0.8](https://github.com/xweiba/location-spoofer/releases/tag/v1.0.8) — 2026-09-24
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# 更新紀錄
|
||||
|
||||
各版本的說明存放於 [`docs/releases/`](releases/) 目錄。
|
||||
|
||||
## 已發佈
|
||||
|
||||
- [v1.0.8](releases/v1.0.8.zh-Hant.md) — 2026-09-24([English](releases/v1.0.8.en.md) · [简体中文](releases/v1.0.8.md))
|
||||
- [v1.0.7](releases/v1.0.7.md) — 2026-09-11(簡體中文)
|
||||
- [v1.0.6](releases/v1.0.6.md) — 2026-09-01(簡體中文)
|
||||
|
||||
更早的版本:[GitHub Releases](https://github.com/xweiba/location-spoofer/releases)。
|
||||
@@ -0,0 +1,29 @@
|
||||
# v1.0.8
|
||||
|
||||
Release date: September 24, 2026
|
||||
|
||||
[简体中文](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.md) · [繁體中文](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.zh-Hant.md)
|
||||
|
||||
This re-release replaces build 9 with **build 10** while keeping the v1.0.8 version.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Fixed the app showing Chinese when a non-Chinese language is preferred: the app now uses only the **first** preferred language. Simplified and Traditional Chinese display Chinese; Italian and other non-Chinese languages display English even if Chinese is second in the preference list.
|
||||
- Added explicit Simplified and Traditional Chinese resources and made English the development-language fallback. Diagnostics, prompts, and generated bug reports follow the same language choice.
|
||||
- Added missing English translations for two hostname-copy messages and regression tests for language selection.
|
||||
- Made English the default repository README, retained a separate Chinese README, added the project's AGPL-3.0 license, and preserved third-party script license and provenance information.
|
||||
- Added contract tests to CI and synchronized the remote-version fallback with the release version.
|
||||
|
||||
## Changes since v1.0.7
|
||||
|
||||
- `5b9fedf` Fix first-preferred-language fallback and prepare v1.0.8
|
||||
- `228b67b` Make English the default README and add AGPL licensing
|
||||
- `f4712f7` Run contract tests in CI and via make test
|
||||
- `393c7cc` Align the built-in fallback version and add consistency checks
|
||||
|
||||
## Self-signing and installation
|
||||
|
||||
- The Release attachment is an **unsigned IPA**. Sign it before installing it on an iPhone.
|
||||
- A free Apple ID and Impactor can be used; a paid developer account is not required.
|
||||
- Keep the Bundle ID `com.paopaolabs.location-spoofer`, App Group `group.com.paopaolabs.location-spoofer`, and existing entitlements when signing.
|
||||
- Free Apple ID signing usually expires after seven days, after which the app needs to be signed and installed again.
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
发布日期:2026-09-24
|
||||
|
||||
[English](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.en.md) · [繁體中文](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.zh-Hant.md)
|
||||
|
||||
本次重新发布以**构建号 10** 替换原构建号 9,版本号仍为 v1.0.8。
|
||||
|
||||
## 主要更新
|
||||
|
||||
- 修复非中文系统语言下错误显示中文的问题:只根据首选语言的**第一项**选择 App 界面语言。简体中文和繁体中文分别显示中文;意大利语及其他非中文语言统一显示英文,即使中文排在首选语言列表的后面。
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# v1.0.8
|
||||
|
||||
發佈日期:2026-09-24
|
||||
|
||||
[English](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.en.md) · [简体中文](https://github.com/xweiba/location-spoofer/blob/v1.0.8/docs/releases/v1.0.8.md)
|
||||
|
||||
本次重新發佈以**建置版本 10** 取代原有的建置版本 9,版本號仍為 v1.0.8。
|
||||
|
||||
## 主要更新
|
||||
|
||||
- 修正非中文系統語言下錯誤顯示中文的問題:App 現在只根據偏好語言的**第一項**選擇介面語言。簡體和繁體中文顯示中文;義大利文及其他非中文語言顯示英文,即使中文排在語言清單的第二項。
|
||||
- 補齊簡體與繁體中文本地化資源,並將英文設為開發語言及預設回退語言。診斷資訊、提示與產生的 Bug 回報也遵循相同的語言選擇規則。
|
||||
- 補上兩處主機名稱複製提示的英文翻譯,並加入語言選擇的迴歸測試。
|
||||
- 將英文設為儲存庫的預設 README,保留獨立的中文文件;加入專案的 AGPL-3.0 授權,並保留第三方腳本原有的授權及來源說明。
|
||||
- 將契約測試加入 CI,並統一遠端版本設定與內建回退版本號。
|
||||
|
||||
## 提交變更摘要
|
||||
|
||||
- `5b9fedf` 修正偏好語言回退邏輯並準備 v1.0.8
|
||||
- `228b67b` 將英文 README 設為預設並加入 AGPL 授權
|
||||
- `f4712f7` 在 CI 與 make test 執行契約測試
|
||||
- `393c7cc` 修正內建回退版本號並加入一致性檢查
|
||||
|
||||
## 自行簽署與安裝
|
||||
|
||||
- Release 附件是**未簽署的 IPA**,安裝到 iPhone 前必須先簽署。
|
||||
- 可以使用免費 Apple ID 和 Impactor 簽署安裝,無須付費開發者帳號。
|
||||
- 簽署時請保留 Bundle ID `com.paopaolabs.location-spoofer`、App Group `group.com.paopaolabs.location-spoofer` 及原有 entitlements。
|
||||
- 免費 Apple ID 的簽署通常只有七天有效期,到期後需要重新簽署並安裝。
|
||||
+1
-1
@@ -16,7 +16,7 @@ settings:
|
||||
base:
|
||||
SWIFT_VERSION: "5.9"
|
||||
MARKETING_VERSION: "1.0.8"
|
||||
CURRENT_PROJECT_VERSION: "9"
|
||||
CURRENT_PROJECT_VERSION: "10"
|
||||
CODE_SIGN_STYLE: Manual
|
||||
CODE_SIGNING_ALLOWED: "NO"
|
||||
CODE_SIGNING_REQUIRED: "NO"
|
||||
|
||||
Reference in New Issue
Block a user