Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0b44f3c
Fix(i18n): correct "For Forker" typo to "For developers" in changelog
Copilot Aug 22, 2026
030ce34
Merge pull request #424 from jason5ng32/copilot/update-change-log-for…
jason5ng32 Aug 22, 2026
8c6e145
Style(preferences): fix Beta badge vertical alignment
Copilot Aug 22, 2026
c978bfb
Merge pull request #425 from jason5ng32/copilot/fix-badge-vertical-al…
jason5ng32 Aug 22, 2026
da8698f
Feat(i18n): add Brazilian Portuguese beta locale
vitorparras Aug 22, 2026
36d6177
Feat(i18n): expand Brazilian Portuguese UI translation
vitorparras Aug 22, 2026
865f4c8
Merge pull request #426 from vitorparras/i18n/pt-br-ui-translation
jason5ng32 Aug 23, 2026
89cbb35
Chore(deps): bump @cloudflare/speedtest and vite
jason5ng32 Aug 23, 2026
8f2751b
Fix(logging): log 403 IP-source fail-over as warning
jason5ng32 Aug 23, 2026
4a2085a
Style(preferences): switch Beta badge to outline variant
jason5ng32 Aug 23, 2026
29ae0ff
Fix(i18n): refine four pt-BR strings
jason5ng32 Aug 23, 2026
46a42b1
Feat(ci): report translation status on locale PRs
jason5ng32 Aug 23, 2026
09b63ac
Feat(ci): greet newly opened PRs
jason5ng32 Aug 23, 2026
b411af1
Fix(i18n): shorten pt-BR navbar labels
jason5ng32 Aug 23, 2026
16d3e16
Fix(ci): treat the i18n report artifact as untrusted text
jason5ng32 Aug 23, 2026
5217815
Improvements
jason5ng32 Aug 23, 2026
10b3368
Fix(ci): render the i18n comment from validated numbers only
jason5ng32 Aug 23, 2026
58bd271
Refactor(ci): drop the i18n PR comment bot
jason5ng32 Aug 23, 2026
5fe62ba
Merge pull request #427 from jason5ng32/dev
jason5ng32 Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ jobs:
# out of sync with package.json, rather than silently rewriting it.
run: pnpm install --frozen-lockfile

- name: Translation status
# Locale progress dashboard into the run summary, so a translation PR's
# author and reviewer see coverage and the next keys to translate without
# a local run. Report only — the script always exits 0; the mechanical
# gate for locale packs lives in pnpm test below.
run: |
{
echo '```text'
node scripts/i18n-status.js
echo '```'
} >> "$GITHUB_STEP_SUMMARY"

- name: Run tests
run: pnpm test

Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/pr-welcome.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Greets every newly opened PR from an outside contributor: first-time
# contributors get the full onboarding message, returning contributors a
# shorter welcome-back one. Maintainer PRs (owner / member / collaborator)
# and bot PRs are skipped.
#
# pull_request_target is safe here precisely because this workflow never
# checks out or executes anything from the PR — it only posts a comment
# with trusted code from the base branch. Keep it that way: no checkout,
# no build steps in this file, ever. It also means the greeting posts
# immediately, even while CI still sits behind the fork-approval gate.
name: PR welcome

on:
pull_request_target:
types: [opened]

permissions:
pull-requests: write

jobs:
welcome:
if: >-
!contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association)
&& github.event.pull_request.user.type != 'Bot'
runs-on: ubuntu-latest

steps:
- name: Post greeting
uses: actions/github-script@v9
with:
script: |
const pr = context.payload.pull_request;
const author = pr.user.login;
const repoUrl = `https://github.com/${process.env.GITHUB_REPOSITORY}`;

// The PR just opened is included in the count, so 1 = first ever.
const { data: search } = await github.rest.search.issuesAndPullRequests({
q: `repo:${context.repo.owner}/${context.repo.repo} is:pr author:${author}`,
per_page: 1,
});
const isFirstTime = search.total_count <= 1;

const firstTime = [
`Thanks for your first PR here, @${author} — contributions like this are what keep MyIP going! 🙏`,
'',
'This project has a single maintainer, so reviews are usually quick but not instant — expect a response within a day or two. A couple of things that speed a merge up:',
'',
'- `pnpm check` green locally (tests + build) is the fastest path through review.',
`- Conventions live in [AGENTS.md](${repoUrl}/blob/dev/AGENTS.md); translation PRs additionally in [TRANSLATING.md](${repoUrl}/blob/dev/TRANSLATING.md).`,
"- If the checks tab says a workflow is *awaiting approval*, that's normal for first-time contributors — the maintainer approves it as part of the review.",
'',
'_This is an automated greeting; a human review follows._',
];

const returning = [
`Thanks for another PR, @${author} — always good to see you back! 🙌`,
'',
'The maintainer will take a look shortly (usually within a day or two). As ever, `pnpm check` green locally is the fastest path through review.',
'',
'_This is an automated greeting; a human review follows._',
];

await github.rest.issues.createComment({
...context.repo,
issue_number: pr.number,
body: (isFirstTime ? firstTime : returning).join('\n'),
});
1 change: 1 addition & 0 deletions common/locale-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const LOCALES = [
{ code: 'zh', nativeName: '简体中文', flag: 'cn', apiTag: 'zh-CN', htmlLang: 'zh-CN', status: 'full' },
{ code: 'fr', nativeName: 'Français', flag: 'fr', apiTag: 'fr', htmlLang: 'fr', status: 'full' },
{ code: 'ru', nativeName: 'Русский', flag: 'ru', apiTag: 'ru', htmlLang: 'ru', status: 'full' },
{ code: 'pt-BR', nativeName: 'Português (Brasil)', flag: 'br', apiTag: 'pt-BR', htmlLang: 'pt-BR', status: 'beta' },
];

// Registry order — also the order the language picker renders.
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/IpInfos.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { transformDataFromIPapi } from '@/utils/transform-ip-data.js';
import { getIPFromIPIP, getIPFromCloudflare_V4, getIPFromCloudflare_V6, getIPFromIPChecking64, getIPFromIPChecking4, getIPFromIPChecking6 } from '@/utils/getips';
import { emitAppEvent, waitForAppEvent } from '@/utils/app-events';
import { useAppCommand } from '@/composables/use-app-command.js';
import { authenticatedFetch, fetchErrorLabel } from '@/utils/authenticated-fetch';
import { authenticatedFetch, fetchErrorLabel, logSourceFetchFailure } from '@/utils/authenticated-fetch';
import IPCard from './ip-infos/IPCard.vue';
import InfoBanner from './widgets/InfoBanner.vue';

Expand Down Expand Up @@ -348,7 +348,7 @@ const fetchIPDetails = async (cardIndex, ip, sourceID = null) => {
return;
}
} catch (error) {
console.error(`Error fetching IP details from source ${source.id} (${fetchErrorLabel(error)}):`, error);
logSourceFetchFailure(`Error fetching IP details from source ${source.id} (${fetchErrorLabel(error)}):`, error);
currentSourceIndex = (currentSourceIndex + 1) % sources.length;
attempts++;
}
Expand Down
Loading
Loading