Skip to content

Commit 36d8fce

Browse files
committed
Merge branch 'master' into release
2 parents 09eb576 + 6f29085 commit 36d8fce

File tree

31 files changed

+2241
-212
lines changed

31 files changed

+2241
-212
lines changed

.env.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ QFIELDCLOUD_SUBSCRIPTION_MODEL=subscription.Subscription
134134
# DEFAULT: 720
135135
QFIELDCLOUD_AUTH_TOKEN_EXPIRATION_HOURS=720
136136

137+
# Whether QFieldCloud should be translated in another language other than English.
138+
# NOTE if there is no full translation in given language, QFieldCloud will be shown in mixture of English and the given language. Also installed Django modules have their own translations that might not be complete.
139+
# VALUES: 0 - English only; 1 - enable other languages
140+
# DEFAULT: 1
141+
QFIELDCLOUD_USE_I18N=1
142+
143+
# QFieldCloud default language that is displayed in the interface
144+
# DEFAULT: "en"
145+
QFIELDCLOUD_DEFAULT_LANGUAGE="en"
146+
137147
# QFieldCloud default timezone that is used when account has no timezone
138148
# DEFAULT: "Europe/Zurich"
139149
QFIELDCLOUD_DEFAULT_TIME_ZONE="Europe/Zurich"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: 🌎 Synchronize translations with Transifex
2+
3+
on:
4+
schedule:
5+
- cron: "0 2 * * *"
6+
workflow_dispatch:
7+
8+
jobs:
9+
10+
sync_translations:
11+
12+
name: Synchronize Transifex translations
13+
runs-on: ubuntu-latest
14+
15+
env:
16+
TX_TOKEN: ${{ secrets.TX_TOKEN }}
17+
18+
steps:
19+
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
with:
23+
token: ${{ secrets.NYUKI_TOKEN }}
24+
25+
- name: Install Transifex CLI
26+
run: |
27+
curl -OL https://github.com/transifex/cli/releases/download/v1.6.17/tx-linux-amd64.tar.gz
28+
tar -xvzf tx-linux-amd64.tar.gz
29+
30+
- name: Copy .env file
31+
run: |
32+
cp .env.example .env
33+
34+
- name: Perform docker pre operations
35+
run: |
36+
docker compose pull
37+
docker compose build
38+
39+
- name: Generate Django translation po files
40+
run: |
41+
docker compose run --user root app python manage.py makemessages -l es
42+
43+
- name: Push translation files to Transifex
44+
run: ./tx push --source
45+
46+
- name: Pull from Transifex
47+
run: ./tx pull --all --minimum-perc 0 --force
48+
49+
- name: Add and commit new translations
50+
uses: EndBug/add-and-commit@v9
51+
with:
52+
message: Synchronize translations
53+
author_name: Translation update 💬
54+
author_email: [email protected]
55+
add: '["docker-app/qfieldcloud/locale"]'

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ Pipfile*
1616
**/site-packages
1717
docker-qgis/libqfieldsync
1818
docker-qgis/qfieldcloud-sdk-python
19+
20+
# compiled translations
21+
docker-app/qfieldcloud/locale/**/*.mo

.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,5 @@ repos:
5050
additional_dependencies: [types-pytz, types-Deprecated, types-PyYAML, types-requests, types-tabulate, types-jsonschema, django-stubs, django-stubs-ext, djangorestframework-stubs]
5151
pass_filenames: false
5252
entry: bash -c 'mypy -p docker-app -p docker-qgis "$@"' --
53+
54+
exclude: 'docker-app/qfieldcloud/locale/.*'

.tx/config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[main]
2+
host = https://www.transifex.com
3+
4+
[o:opengisch:p:qfieldcloud:r:qfieldcloud]
5+
file_filter = docker-app/qfieldcloud/locale/<lang>/LC_MESSAGES/django.po
6+
source_file = docker-app/qfieldcloud/locale/en/LC_MESSAGES/django.po
7+
type = PO
8+
resource_name = QFieldCloud

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ Now you can get started by adding the first user that would also be a super user
7676

7777
docker compose run app python manage.py createsuperuser --username super_user --email [email protected]
7878

79+
If QFieldCloud needs to be translated, you can compile the translations using Django's tooling:
80+
81+
docker compose run --user root app python manage.py compilemessages
82+
7983
### Dependencies
8084

8185
QFieldCloud uses [`pip-compile`](https://pypi.org/project/pip-tools/) to manage it's dependencies.
@@ -84,7 +88,7 @@ When a `pip` a dependency is changed, the developer should produce the new `requ
8488

8589
docker compose run --rm pipcompile
8690

87-
Alterantively, one can create only a `requirements.txt` file for a single `requirements.in`:
91+
Alternatively, one can create only a `requirements.txt` file for a single `requirements.in`:
8892

8993
docker compose run --rm pipcompile pip-compile --no-strip-extras -o requirements/requirements_worker_wrapper.txt requirements/requirements_worker_wrapper.in
9094

docker-app/qfieldcloud/core/admin.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ class ProjectForm(ModelForm):
745745

746746
class Meta:
747747
model = Project
748-
widgets = {"project_filename": widgets.TextInput()}
748+
widgets = {"the_qgis_file_name": widgets.TextInput()}
749749
fields = "__all__" # required for Django 3.x
750750

751751

@@ -774,7 +774,7 @@ class ProjectAdmin(QFieldCloudModelAdmin):
774774
"owner",
775775
"status",
776776
"status_code",
777-
"project_filename",
777+
"the_qgis_file_name",
778778
"overwrite_conflicts",
779779
"has_restricted_projectfiles",
780780
"file_storage_bytes",
@@ -943,6 +943,7 @@ class JobAdmin(QFieldCloudModelAdmin):
943943
"status",
944944
"error_type",
945945
"type",
946+
"qgis_version",
946947
"created_at",
947948
"updated_at",
948949
"started_at",
@@ -1214,14 +1215,14 @@ def response_change(self, request, delta):
12141215
return super().response_change(request, delta)
12151216

12161217
def apply_delta(self, request, delta):
1217-
if not delta.project.project_filename:
1218+
if not delta.project.has_the_qgis_file:
12181219
self.message_user(request, "Missing project file")
12191220
raise exceptions.NoQGISProjectError()
12201221

12211222
if not jobs.apply_deltas(
12221223
delta.project,
12231224
request.user,
1224-
delta.project.project_filename,
1225+
delta.project.the_qgis_file_name,
12251226
delta.project.overwrite_conflicts,
12261227
delta_ids=[str(delta.id)],
12271228
):

docker-app/qfieldcloud/core/management/commands/calcprojectstorage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def handle(self, *args, **options):
2525
extra_filters["file_storage_bytes"] = 0
2626

2727
projects_qs = Project.objects.filter(
28-
project_filename__isnull=False,
28+
the_qgis_filename__isnull=False,
2929
**extra_filters,
3030
).order_by("-updated_at")
3131
total_count = projects_qs.count()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 4.2.17 on 2025-01-23 19:25
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("core", "0079_organizationmember_created_at_and_more"),
9+
]
10+
11+
operations = [
12+
migrations.RenameField(
13+
model_name="project",
14+
old_name="project_filename",
15+
new_name="the_qgis_file_name",
16+
),
17+
]

docker-app/qfieldcloud/core/models.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ class Meta:
10371037
)
10381038

10391039
description = models.TextField(blank=True)
1040-
project_filename = models.TextField(blank=True, null=True)
1040+
the_qgis_file_name = models.TextField(blank=True, null=True)
10411041
project_details = models.JSONField(blank=True, null=True)
10421042
is_public = models.BooleanField(
10431043
default=False,
@@ -1121,6 +1121,10 @@ class Meta:
11211121
choices=PackagingOffliner.choices,
11221122
)
11231123

1124+
@property
1125+
def has_the_qgis_file(self) -> bool:
1126+
return bool(self.the_qgis_file_name)
1127+
11241128
@property
11251129
def owner_aware_storage_keep_versions(self) -> int:
11261130
"""Determine the storage versions to keep based on the owner's subscription plan and project settings.
@@ -1257,7 +1261,7 @@ def needs_repackaging(self) -> bool:
12571261
def problems(self) -> list[dict]:
12581262
problems = []
12591263

1260-
if not self.project_filename:
1264+
if not self.has_the_qgis_file:
12611265
problems.append(
12621266
{
12631267
"layer": None,
@@ -1349,7 +1353,7 @@ def status(self) -> "Project.Status":
13491353
max_premium_collaborators_per_private_project = self.owner.useraccount.current_subscription.plan.max_premium_collaborators_per_private_project
13501354

13511355
# TODO use self.problems to get if there are project problems
1352-
if not self.project_filename or not self.project_details:
1356+
if not self.has_the_qgis_file or not self.project_details:
13531357
status = Project.Status.FAILED
13541358
status_code = Project.StatusCode.FAILED_PROCESS_PROJECTFILE
13551359
elif (
@@ -1764,6 +1768,30 @@ def fallback_output(self) -> str:
17641768
"The job ended in unknown state. Please verify the project is configured properly, try again and contact QFieldCloud support for more information."
17651769
)
17661770

1771+
@property
1772+
def qgis_version(self) -> str | None:
1773+
"""Returns QGIS app version used for the job.
1774+
1775+
The QGIS version is the one coming from the instanciated worker QGIS app.
1776+
The version number would be in `Major.Minor.Patch-NAME` format, e.g. 3.40.2-Bratislava
1777+
1778+
Returns:
1779+
str | None: QGIS version if found else None.
1780+
"""
1781+
if not self.feedback:
1782+
return None
1783+
1784+
feedback_step_data = self.get_feedback_step_data("start_qgis_app")
1785+
1786+
if not feedback_step_data:
1787+
return None
1788+
1789+
if "qgis_version" in feedback_step_data["returns"]:
1790+
qgis_version = feedback_step_data["returns"]["qgis_version"]
1791+
return qgis_version
1792+
1793+
return None
1794+
17671795
def check_can_be_created(self):
17681796
from qfieldcloud.core.permissions_utils import (
17691797
check_supported_regarding_owner_account,

0 commit comments

Comments
 (0)