mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-22 17:46:59 +00:00
Add translations
This commit is contained in:
parent
9d25249b6d
commit
33f758bbbc
@ -16,35 +16,53 @@ JSX_TEXT_REGEX = re.compile(r'>\s*([A-Z][a-z].*?)\s*<')
|
|||||||
def is_excluded(path):
|
def is_excluded(path):
|
||||||
return any(excluded in path for excluded in EXCLUDED_DIRS)
|
return any(excluded in path for excluded in EXCLUDED_DIRS)
|
||||||
|
|
||||||
|
def is_ignorable(text):
|
||||||
|
return (
|
||||||
|
re.fullmatch(r'[A-Z0-9_]+', text) and 'action' in text
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_console_log_line(line):
|
||||||
|
return any(kw in line for kw in ['console.log', 'console.error', 'console.warn'])
|
||||||
|
|
||||||
def find_untranslated_strings(file_path):
|
def find_untranslated_strings(file_path):
|
||||||
issues = []
|
issues = []
|
||||||
with open(file_path, 'r', encoding='utf-8') as f:
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
lines = content.splitlines()
|
||||||
|
|
||||||
# Match suspicious string literals
|
for idx, line in enumerate(lines, start=1):
|
||||||
for match in STRING_LITERAL_REGEX.finditer(content):
|
if is_console_log_line(line):
|
||||||
string = match.group(1)
|
continue # Skip entire line if it's a console log statement
|
||||||
if not any(fn + '(' in content[match.start()-10:match.start()] for fn in I18N_FUNCTIONS):
|
|
||||||
issues.append({
|
|
||||||
'file': file_path,
|
|
||||||
'position': match.start(),
|
|
||||||
'type': 'StringLiteral',
|
|
||||||
'text': string.strip()
|
|
||||||
})
|
|
||||||
|
|
||||||
# Match JSX text nodes
|
# Match suspicious string literals
|
||||||
for match in JSX_TEXT_REGEX.finditer(content):
|
for match in STRING_LITERAL_REGEX.finditer(line):
|
||||||
text = match.group(1)
|
string = match.group(1).strip()
|
||||||
if not text.strip().startswith('{t('): # naive check
|
if is_ignorable(string):
|
||||||
issues.append({
|
continue
|
||||||
'file': file_path,
|
if not any(fn + '(' in line[:match.start()] for fn in I18N_FUNCTIONS):
|
||||||
'position': match.start(),
|
issues.append({
|
||||||
'type': 'JSXText',
|
'file': file_path,
|
||||||
'text': text.strip()
|
'line': idx,
|
||||||
})
|
'type': 'StringLiteral',
|
||||||
|
'text': string
|
||||||
|
})
|
||||||
|
|
||||||
|
# Match JSX text nodes
|
||||||
|
for match in JSX_TEXT_REGEX.finditer(line):
|
||||||
|
text = match.group(1).strip()
|
||||||
|
if is_ignorable(text):
|
||||||
|
continue
|
||||||
|
if not text.startswith('{t('):
|
||||||
|
issues.append({
|
||||||
|
'file': file_path,
|
||||||
|
'line': idx,
|
||||||
|
'type': 'JSXText',
|
||||||
|
'text': text
|
||||||
|
})
|
||||||
|
|
||||||
return issues
|
return issues
|
||||||
|
|
||||||
|
|
||||||
def scan_directory(directory):
|
def scan_directory(directory):
|
||||||
all_issues = []
|
all_issues = []
|
||||||
for root, _, files in os.walk(directory):
|
for root, _, files in os.walk(directory):
|
||||||
@ -64,7 +82,7 @@ def save_report(results, output_file):
|
|||||||
json.dump(results, f, indent=2)
|
json.dump(results, f, indent=2)
|
||||||
elif ext.lower() == '.csv':
|
elif ext.lower() == '.csv':
|
||||||
with open(output_file, 'w', newline='', encoding='utf-8') as f:
|
with open(output_file, 'w', newline='', encoding='utf-8') as f:
|
||||||
writer = csv.DictWriter(f, fieldnames=['file', 'position', 'type', 'text'])
|
writer = csv.DictWriter(f, fieldnames=['file', 'line', 'type', 'text'])
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
for row in results:
|
for row in results:
|
||||||
writer.writerow(row)
|
writer.writerow(row)
|
||||||
|
@ -10,6 +10,7 @@ import { saveToLocalStorage } from '../components/Apps/AppsNavBarDesktop';
|
|||||||
import { base64ToUint8Array } from '../qdn/encryption/group-encryption';
|
import { base64ToUint8Array } from '../qdn/encryption/group-encryption';
|
||||||
import { uint8ArrayToObject } from '../backgroundFunctions/encryption';
|
import { uint8ArrayToObject } from '../backgroundFunctions/encryption';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const useHandlePrivateApps = () => {
|
export const useHandlePrivateApps = () => {
|
||||||
const [status, setStatus] = useState('');
|
const [status, setStatus] = useState('');
|
||||||
@ -20,8 +21,8 @@ export const useHandlePrivateApps = () => {
|
|||||||
setInfoSnackCustom,
|
setInfoSnackCustom,
|
||||||
} = useContext(MyContext);
|
} = useContext(MyContext);
|
||||||
const setSortablePinnedApps = useSetAtom(sortablePinnedAppsAtom);
|
const setSortablePinnedApps = useSetAtom(sortablePinnedAppsAtom);
|
||||||
|
|
||||||
const setSettingsLocalLastUpdated = useSetAtom(settingsLocalLastUpdatedAtom);
|
const setSettingsLocalLastUpdated = useSetAtom(settingsLocalLastUpdatedAtom);
|
||||||
|
const { t } = useTranslation(['auth', 'core', 'group']);
|
||||||
|
|
||||||
const openApp = async (
|
const openApp = async (
|
||||||
privateAppProperties,
|
privateAppProperties,
|
||||||
@ -29,7 +30,7 @@ export const useHandlePrivateApps = () => {
|
|||||||
setLoadingStatePrivateApp
|
setLoadingStatePrivateApp
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
if (setLoadingStatePrivateApp) {
|
if (setLoadingStatePrivateApp) { // TODO translate
|
||||||
setLoadingStatePrivateApp(`Downloading and decrypting private app.`);
|
setLoadingStatePrivateApp(`Downloading and decrypting private app.`);
|
||||||
}
|
}
|
||||||
setOpenSnackGlobal(true);
|
setOpenSnackGlobal(true);
|
||||||
@ -173,7 +174,7 @@ export const useHandlePrivateApps = () => {
|
|||||||
});
|
});
|
||||||
setInfoSnackCustom({
|
setInfoSnackCustom({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: 'Opened',
|
message: {t('core:message.generic.opened', { postProcess: 'capitalizeFirstChar' })},
|
||||||
});
|
});
|
||||||
if (setLoadingStatePrivateApp) {
|
if (setLoadingStatePrivateApp) {
|
||||||
setLoadingStatePrivateApp(``);
|
setLoadingStatePrivateApp(``);
|
||||||
@ -206,7 +207,12 @@ export const useHandlePrivateApps = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (setLoadingStatePrivateApp) {
|
if (setLoadingStatePrivateApp) {
|
||||||
setLoadingStatePrivateApp(
|
setLoadingStatePrivateApp(
|
||||||
`Error! ${error?.message || 'Unable to build private app.'}`
|
`Error! ${
|
||||||
|
error?.message ||
|
||||||
|
t('core:message.error.unable_build_app', {
|
||||||
|
postProcess: 'capitalizeFirstChar',
|
||||||
|
})
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
@ -214,7 +220,11 @@ export const useHandlePrivateApps = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
setInfoSnackCustom({
|
setInfoSnackCustom({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: error?.message || 'Unable to fetch app',
|
message:
|
||||||
|
error?.message ||
|
||||||
|
t('core:message.error.unable_fetch_app', {
|
||||||
|
postProcess: 'capitalizeFirstChar',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -172,8 +172,10 @@
|
|||||||
"rating_option": "cannot find rating option",
|
"rating_option": "cannot find rating option",
|
||||||
"save_qdn": "unable to save to QDN",
|
"save_qdn": "unable to save to QDN",
|
||||||
"send_failed": "failed to send",
|
"send_failed": "failed to send",
|
||||||
|
"unable_build_app": "unable to build private app",
|
||||||
"unable_download_image": "unable to download IMAGE. Please try again later by clicking the refresh button",
|
"unable_download_image": "unable to download IMAGE. Please try again later by clicking the refresh button",
|
||||||
"unable_encrypt_app": "unable to encrypt app. App not published'",
|
"unable_encrypt_app": "unable to encrypt app. App not published'",
|
||||||
|
"unable_fetch_app": "unable to build private app",
|
||||||
"unable_publish_app": "unable to publish app",
|
"unable_publish_app": "unable to publish app",
|
||||||
"unable_publish_image": "unable to publish image",
|
"unable_publish_image": "unable to publish image",
|
||||||
"unable_rate": "unable to rate",
|
"unable_rate": "unable to rate",
|
||||||
@ -215,6 +217,7 @@
|
|||||||
"no_pinned_changes": "you currently do not have any changes to your pinned apps",
|
"no_pinned_changes": "you currently do not have any changes to your pinned apps",
|
||||||
"no_results": "no results",
|
"no_results": "no results",
|
||||||
"one_app_per_name": "note: Currently, only one App and Website is allowed per Name.",
|
"one_app_per_name": "note: Currently, only one App and Website is allowed per Name.",
|
||||||
|
"opened": "opened",
|
||||||
"overwrite_qdn": "overwrite to QDN",
|
"overwrite_qdn": "overwrite to QDN",
|
||||||
"password_confirm": "please confirm a password",
|
"password_confirm": "please confirm a password",
|
||||||
"password_enter": "please enter a password",
|
"password_enter": "please enter a password",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user