Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 88 additions & 0 deletions .github/workflows/weblate-update-pot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Weblate Update POT

on:
schedule:
# run every working day (Monday-Friday) at 1:42AM UTC
- cron: "42 1 * * 0-4"

# allow running manually
workflow_dispatch:

jobs:
update-pot:
# do not run in forks
if: github.repository == 'openSUSE/agama'

runs-on: ubuntu-latest

container:
image: registry.opensuse.org/opensuse/tumbleweed:latest

steps:
- name: Configure and refresh repositories
# disable unused repositories to have a faster refresh
run: zypper modifyrepo -d repo-non-oss repo-openh264 repo-update && zypper ref

- name: Install tools
run: zypper --non-interactive install --no-recommends diffutils git gettext-tools

- name: Checkout Agama sources
uses: actions/checkout@v3
with:
path: agama

- name: Generate POT file
# TODO: use a shared script for this
run: |
cd agama/web
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if I get it, it generate pot file only from web part and not from service ( aka ruby code ) and from rust code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, web frontend only. As noted in the TODO above, this should be replaced by some other script.

xgettext --default-domain=agama --output=- --language=C --keyword= \
--keyword=_:1,1t --keyword=_:1c,2,2t --keyword=C_:1c,2 \
--keyword=N_ --keyword=NC_:1c,2 --foreign-user \
--copyright-holder="SuSE Linux Products GmbH, Nuernberg" \
--from-code=UTF-8 --add-comments=TRANSLATORS --sort-by-file \
$(find . ! -name cockpit.js -name '*.js' -o ! -name '*.test.jsx' -name '*.jsx') | \
sed '/^#/ s/, c-format//' > agama.pot
msgfmt --statistics agama.pot

- name: Validate the generated POT file
run: msgfmt --check-format agama/web/agama.pot

- name: Checkout Weblate sources
uses: actions/checkout@v3
with:
path: agama-weblate
repository: openSUSE/agama-weblate
token: ${{ secrets.GH_TOKEN }}

- name: Configure Git
run: |
git config --global user.name "YaST Bot"
git config --global user.email "yast-devel@opensuse.org"

- name: Update POT file
run: |
mkdir -p agama-weblate/web
cp agama/web/agama.pot agama-weblate/web/agama.pot

# any change besides the timestamp in the POT file?
- name: Check changes
id: check_changes
run: |
git -C agama-weblate diff --ignore-matching-lines="POT-Creation-Date:" web/agama.pot > pot.diff

if [ -s pot.diff ]; then
echo "POT file updated"
echo "pot_updated=true" >> $GITHUB_OUTPUT
else
echo "POT file unchanged"
echo "pot_updated=false" >> $GITHUB_OUTPUT
fi

- name: Push updated POT file
# run only when the POT file has been updated
if: steps.check_changes.outputs.pot_updated == 'true'
run: |
cd agama-weblate
git add web/agama.pot
git commit -m "Update POT file"$'\n\n'"Agama commit: $GITHUB_SHA"
git push
1 change: 1 addition & 0 deletions web/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"filename",
"fullname",
"freedesktop",
"gettext",
"ibft",
"ifaces",
"ipaddr",
Expand Down
9 changes: 6 additions & 3 deletions web/src/components/core/FileViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import { Loading } from "~/components/layout";

import cockpit from "../../lib/cockpit";

// FIXME: replace by a wrapper, this is just for testing
const _ = cockpit.gettext;

export default function FileViewer({ file, title, onCloseCallback }) {
// the popup is visible
const [isOpen, setIsOpen] = useState(true);
Expand Down Expand Up @@ -61,13 +64,13 @@ export default function FileViewer({ file, title, onCloseCallback }) {
title={title || file}
className="large"
>
{state === "loading" && <Loading text="Reading file..." />}
{state === "loading" && <Loading text={_("Reading file...")} />}
{(content === null || error) &&
<Alert
isInline
isPlain
variant="warning"
title="Cannot read the file"
title={_("Cannot read the file")}
>
{error}
</Alert>}
Expand All @@ -76,7 +79,7 @@ export default function FileViewer({ file, title, onCloseCallback }) {
</div>

<Popup.Actions>
<Popup.Confirm onClick={close} autoFocus>Close</Popup.Confirm>
<Popup.Confirm onClick={close} autoFocus>{_("Close")}</Popup.Confirm>
</Popup.Actions>
</Popup>
);
Expand Down
4 changes: 3 additions & 1 deletion web/src/components/core/FileViewer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import React from "react";

import { screen, waitFor, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
import { mockGettext, plainRender } from "~/test-utils";
import { FileViewer } from "~/components/core";
import cockpit from "../../lib/cockpit";

Expand All @@ -44,6 +44,8 @@ const file_name = "/testfile";
const content = "Read file content";
const title = "YaST Logs";

mockGettext();

describe("FileViewer", () => {
beforeEach(() => {
readFn.mockResolvedValue(content);
Expand Down
15 changes: 15 additions & 0 deletions web/src/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { render } from "@testing-library/react";
import { createClient } from "~/client/index";
import { InstallerClientProvider } from "~/context/installer";
import { NotificationProvider } from "~/context/notification";
import cockpit from "./lib/cockpit";

/**
* Internal mock for manipulating routes, using ["/"] by default
Expand Down Expand Up @@ -165,11 +166,25 @@ const withNotificationProvider = (content) => {
);
};

/**
* Mocks the cockpit.gettext() method with an identity function (returns
* the original untranslated text)
*/
const mockGettext = () => {
const gettextFn = jest.fn();
gettextFn.mockImplementation((text) => {
return text;
});

cockpit.gettext.mockImplementation(gettextFn);
};

export {
plainRender,
installerRender,
createCallbackMock,
mockComponent,
mockGettext,
mockLayout,
mockNavigateFn,
mockRoutes,
Expand Down