Skip to content

Commit 183f1cd

Browse files
committed
Add a tool to detect possible unused language keys and remove those which can be confirmed
1 parent 637070e commit 183f1cd

File tree

3 files changed

+94
-37
lines changed

3 files changed

+94
-37
lines changed

build/clean-locales.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
//go:build ignore
5+
6+
package main
7+
8+
import (
9+
"errors"
10+
"os"
11+
"path/filepath"
12+
"strings"
13+
14+
"code.gitea.io/gitea/modules/setting"
15+
)
16+
17+
func searchDirs(key string) (bool, error) {
18+
for _, dir := range []string{
19+
"cmd",
20+
"models",
21+
"modules",
22+
"routers",
23+
"services",
24+
"templates",
25+
} {
26+
found, err := searchLocaleFiles(dir, key)
27+
if err != nil {
28+
return false, err
29+
}
30+
if found {
31+
return true, nil
32+
}
33+
}
34+
return false, nil
35+
}
36+
37+
func searchLocaleFiles(dir, key string) (bool, error) {
38+
errFound := errors.New("found")
39+
err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
40+
if err != nil {
41+
return err
42+
}
43+
if d.IsDir() || (!strings.HasSuffix(d.Name(), ".go") && !strings.HasSuffix(d.Name(), ".tmpl")) {
44+
return nil
45+
}
46+
47+
bs, err := os.ReadFile(path)
48+
if err != nil {
49+
return err
50+
}
51+
if strings.Contains(string(bs), `"`+key+`"`) {
52+
return errFound
53+
}
54+
55+
return nil
56+
})
57+
if err == errFound {
58+
return true, nil
59+
}
60+
return false, err
61+
}
62+
63+
func main() {
64+
if len(os.Args) != 1 {
65+
println("usage: clean-locales")
66+
os.Exit(1)
67+
}
68+
69+
iniFile, err := setting.NewConfigProviderForLocale("options/locale/locale_en-US.ini")
70+
if err != nil {
71+
panic(err)
72+
}
73+
74+
for _, section := range iniFile.Sections() {
75+
for _, key := range section.Keys() {
76+
var trKey string
77+
if section.Name() == "" || section.Name() == "DEFAULT" {
78+
trKey = key.Name()
79+
} else {
80+
trKey = section.Name() + "." + key.Name()
81+
}
82+
83+
found, err := searchDirs(trKey)
84+
if err != nil {
85+
panic(err)
86+
}
87+
if !found {
88+
println("unused locale key:", trKey)
89+
}
90+
}
91+
}
92+
}

options/locale/locale_en-US.ini

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,17 @@ webauthn_error_unable_to_process = The server could not process your request.
4949
webauthn_error_duplicated = The security key is not permitted for this request. Please make sure that the key is not already registered.
5050
webauthn_error_empty = You must set a name for this key.
5151
webauthn_error_timeout = Timeout reached before your key could be read. Please reload this page and retry.
52-
webauthn_reload = Reload
5352

5453
repository = Repository
5554
organization = Organization
5655
mirror = Mirror
5756
issue_milestone = Milestone
5857
new_repo = New Repository
5958
new_migrate = New Migration
60-
new_mirror = New Mirror
6159
new_fork = New Repository Fork
6260
new_org = New Organization
63-
new_project = New Project
6461
new_project_column = New Column
65-
manage_org = Manage Organizations
6662
admin_panel = Site Administration
67-
account_settings = Account Settings
6863
settings = Settings
6964
your_profile = Profile
7065
your_starred = Starred
@@ -368,13 +363,9 @@ config_write_file_prompt = These configuration options will be written into: %s
368363
[home]
369364
nav_menu = Navigation Menu
370365
uname_holder = Username or Email Address
371-
password_holder = Password
372366
switch_dashboard_context = Switch Dashboard Context
373367
my_repos = Repositories
374-
show_more_repos = Show more repositories…
375-
collaborative_repos = Collaborative Repositories
376368
my_orgs = My Organizations
377-
my_mirrors = My Mirrors
378369
view_home = View %s
379370
filter = Other Filters
380371
filter_by_team_repositories = Filter by team repositories
@@ -435,7 +426,6 @@ resent_limit_prompt = You have already requested an activation email recently. P
435426
has_unconfirmed_mail = Hi %s, you have an unconfirmed email address (<b>%s</b>). If you haven't received a confirmation email or need to resend a new one, please click on the button below.
436427
change_unconfirmed_mail_address = If your registration email address is incorrect, you can change it here and resend a new confirmation email.
437428
resend_mail = Click here to resend your activation email
438-
email_not_associate = The email address is not associated with any account.
439429
send_reset_mail = Send Account Recovery Email
440430
reset_password = Account Recovery
441431
invalid_code = Your confirmation code is invalid or has expired.
@@ -453,7 +443,6 @@ twofa_passcode_incorrect = Your passcode is incorrect. If you misplaced your dev
453443
twofa_scratch_token_incorrect = Your scratch code is incorrect.
454444
twofa_required = You must setup Two-Factor Authentication to get access to repositories, or try to login again.
455445
login_userpass = Sign In
456-
login_openid = OpenID
457446
oauth_signup_tab = Register New Account
458447
oauth_signup_title = Complete New Account
459448
oauth_signup_submit = Complete Account
@@ -481,7 +470,6 @@ authorize_application_with_scopes = With scopes: %s
481470
authorize_title = Authorize "%s" to access your account?
482471
authorization_failed = Authorization failed
483472
authorization_failed_desc = The authorization failed because we detected an invalid request. Please contact the maintainer of the app you have tried to authorize.
484-
sspi_auth_failed = SSPI authentication failed
485473
password_pwned = The password you chose is on a <a target="_blank" rel="noopener noreferrer" href="%s">list of stolen passwords</a> previously exposed in public data breaches. Please try again with a different password and consider changing this password elsewhere too.
486474
password_pwned_err = Could not complete request to HaveIBeenPwned
487475
last_admin = You cannot remove the last admin. There must be at least one admin.
@@ -513,8 +501,6 @@ reset_password = Recover your account
513501
reset_password.title = %s, you have requested to recover your account
514502
reset_password.text = Please click the following link to recover your account within <b>%s</b>:
515503
516-
register_success = Registration successful
517-
518504
issue_assigned.pull = @%[1]s assigned you to pull request %[2]s in repository %[3]s.
519505
issue_assigned.issue = @%[1]s assigned you to issue %[2]s in repository %[3]s.
520506
@@ -559,30 +545,12 @@ yes = Yes
559545
no = No
560546
confirm = Confirm
561547
cancel = Cancel
562-
modify = Update
563548
564549
[form]
565-
UserName = Username
566-
RepoName = Repository name
567-
Email = Email address
568-
Password = Password
569-
Retype = Confirm Password
570-
SSHTitle = SSH key name
571-
HttpsUrl = HTTPS URL
572-
PayloadUrl = Payload URL
573-
TeamName = Team name
574-
AuthName = Authorization name
575-
AdminEmail = Admin email
576550
577551
NewBranchName = New branch name
578-
CommitSummary = Commit summary
579-
CommitMessage = Commit message
580-
CommitChoice = Commit choice
581-
TreeName = File path
582-
Content = Content
583552
584553
SSPISeparatorReplacement = Separator
585-
SSPIDefaultLanguage = Default Language
586554
587555
require_error = ` cannot be empty.`
588556
alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.`
@@ -607,7 +575,6 @@ username_been_taken = The username is already taken.
607575
username_change_not_local_user = Non-local users are not allowed to change their username.
608576
change_username_disabled = Changing username is disabled.
609577
change_full_name_disabled = Changing full name is disabled.
610-
username_has_not_been_changed = Username has not been changed
611578
repo_name_been_taken = The repository name is already used.
612579
repository_force_private = Force Private is enabled: private repositories cannot be made public.
613580
repository_files_already_exist = Files already exist for this repository. Contact the system administrator.
@@ -718,7 +685,6 @@ password = Password
718685
security = Security
719686
avatar = Avatar
720687
ssh_gpg_keys = SSH / GPG Keys
721-
social = Social Accounts
722688
applications = Applications
723689
orgs = Manage Organizations
724690
repos = Repositories
@@ -1281,7 +1247,6 @@ release = Release
12811247
releases = Releases
12821248
tag = Tag
12831249
released_this = released this
1284-
tagged_this = tagged this
12851250
file.title = %s at %s
12861251
file_raw = Raw
12871252
file_history = History

routers/web/user/setting/profile.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func ProfilePost(ctx *context.Context) {
7171

7272
if form.Name != "" {
7373
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureChangeUsername) {
74-
ctx.Flash.Error(ctx.Tr("user.form.change_username_disabled"))
74+
ctx.Flash.Error(ctx.Tr("form.change_username_disabled"))
7575
ctx.Redirect(setting.AppSubURL + "/user/settings")
7676
return
7777
}
@@ -107,7 +107,7 @@ func ProfilePost(ctx *context.Context) {
107107

108108
if form.FullName != "" {
109109
if user_model.IsFeatureDisabledWithLoginType(ctx.Doer, setting.UserFeatureChangeFullName) {
110-
ctx.Flash.Error(ctx.Tr("user.form.change_full_name_disabled"))
110+
ctx.Flash.Error(ctx.Tr("form.change_full_name_disabled"))
111111
ctx.Redirect(setting.AppSubURL + "/user/settings")
112112
return
113113
}

0 commit comments

Comments
 (0)