Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c094876
Refactor sorting logic in sort_en_xml.py to filter and sort <string> …
MightyMCoder Jun 24, 2025
0e1778e
Refactor XML sorting logic to preserve comments and improve buffer ha…
MightyMCoder Jun 24, 2025
b27a5fd
Refactor commit logic in sort-en-xml.yml to streamline file handling …
MightyMCoder Jun 24, 2025
2665c7b
Refactor workflow steps in sort-en-xml.yml to clarify script executio…
MightyMCoder Jun 24, 2025
99ac8c7
chore: sort en.xml alphabetically
Jun 24, 2025
39fd638
Refactor sorting logic in sort_en_xml.py to simplify buffer handling …
MightyMCoder Jun 24, 2025
d7c742c
chore: sort en.xml alphabetically
Jun 24, 2025
d036934
fix language file sorting workflow
MightyMCoder Jun 24, 2025
ad1fbc3
feat: add workflow and script to check for unused translation keys
MightyMCoder Jun 24, 2025
b404f01
fix: correct script path in unused string checker workflow
MightyMCoder Jun 24, 2025
6851f4d
fix: update unused string checker workflow to handle errors correctly
MightyMCoder Jun 24, 2025
ed972bf
fix: update workflows to ensure proper handling of unused strings and…
MightyMCoder Jun 24, 2025
9350965
fix: remove error message from unused string checker command
MightyMCoder Jun 24, 2025
7fddc85
fix: add debug output for event name and check outcome in unused stri…
MightyMCoder Jun 24, 2025
f92f52f
fix: update unused string checker workflow to annotate warnings for u…
MightyMCoder Jun 24, 2025
abca4a2
fix: update conditions for jq installation and PR review in unused st…
MightyMCoder Jun 24, 2025
ed54d69
fix: remove jq installation step from unused string checker workflow
MightyMCoder Jun 24, 2025
247c5f6
fix: remove unused strings from language files
MightyMCoder Jun 24, 2025
08ab037
fix: add approval step for PRs with no unused translation keys
MightyMCoder Jun 24, 2025
1e067b4
Revert "fix: add approval step for PRs with no unused translation keys"
MightyMCoder Jun 24, 2025
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
30 changes: 30 additions & 0 deletions .github/scripts/check_unused_strings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os, re, xml.etree.ElementTree as ET
import argparse

p = argparse.ArgumentParser()
p.add_argument('--exclude', default='', help='Comma‑separated dirs to skip')
args = p.parse_args()
excl = {d.strip() for d in args.exclude.split(',') if d.strip()}

root = ET.parse('languages/en.xml').getroot()
keys = [e.attrib['name'] for e in root.findall('.//string')
if re.fullmatch(r'[A-Z0-9_]+', e.attrib['name'])]

unused = []
for k in keys:
used = False
for dp, _, fs in os.walk('.'):
if any(part in excl for part in dp.split(os.sep)):
continue
for f in fs:
if f.endswith(('.php','.js','.html','.tpl')):
if k in open(os.path.join(dp, f), 'r', errors='ignore').read():
Comment thread
MightyMCoder marked this conversation as resolved.
used = True; break
if used: break
if not used:
unused.append(k)

if unused:
for k in unused:
print(f"UNUSED: {k}")
exit(1) # triggers warning via continue-on-error
39 changes: 34 additions & 5 deletions .github/scripts/sort_en_xml.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import xml.etree.ElementTree as ET
from lxml import etree

file = 'languages/en.xml'
tree = ET.parse(file)

# Load XML with comments preserved
parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse(file, parser)
root = tree.getroot()
root[:] = sorted(root, key=lambda e: e.attrib.get('name',''))
ET.indent(tree, space=" ")
tree.write(file, encoding='utf-8', xml_declaration=True)

new_children = []
buffer = []

def flush_buffer():
"""Sort and add all <string> elements in the buffer."""
if buffer:
sorted_strings = sorted(buffer, key=lambda e: e.attrib.get('name', ''))
new_children.extend(sorted_strings)
buffer.clear()

for elem in root.iterchildren():
if isinstance(elem, etree._Comment):
flush_buffer()
new_children.append(elem)
elif elem.tag == 'string':
buffer.append(elem)
else:
flush_buffer()
new_children.append(elem)

# Flush anything left at the end
flush_buffer()

# Replace root content
root[:] = new_children

# Save result
tree.write(file, encoding='utf-8', xml_declaration=True, pretty_print=True)
print("en.xml successfully sorted.")
61 changes: 61 additions & 0 deletions .github/workflows/check-unused-strings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Check Unused Strings

on:
push:
branches:
- master
paths:
- languages/en.xml
pull_request:
branches:
- master
paths:
- languages/en.xml
workflow_dispatch:

permissions:
contents: read
pull-requests: write

jobs:
unused-strings:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Run unused‑string checker
id: check
run: |
python .github/scripts/check_unused_strings.py --exclude .github > unused_keys.txt

- name: Annotate warning if unused
if: failure()
continue-on-error: true
run: |
echo "::warning file=en.xml::Detected unused translation keys. Please review."

- name: Ensure jq is installed
if: failure()
continue-on-error: true
run: sudo apt-get update && sudo apt-get install -y jq

- name: Post PR review with unused keys
if: ${{ github.event_name == 'pull_request' && failure() }}
continue-on-error: true
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
PR_NUMBER=$(jq --raw-output .number "$GITHUB_EVENT_PATH")
BODY=$(echo -e "**WARNING: Unused translation keys detected**\n\n\`\`\`\n$(cat unused_keys.txt)\n\`\`\`\nPlease consider removing or using these keys." | jq -Rs .)

curl -s -X POST -H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Content-Type: application/json" \
https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews \
-d "{\"body\": $BODY, \"event\": \"REQUEST_CHANGES\"}"
19 changes: 15 additions & 4 deletions .github/workflows/sort-en-xml.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Sort en.xml

on:
push:
branches:
- master
paths:
- languages/en.xml
workflow_dispatch:

jobs:
Expand All @@ -15,15 +20,21 @@ jobs:
with:
python-version: '3.x'

- name: Sort en.xml
- name: Install lxml
run: pip install lxml

- name: Run sort script
run: python .github/scripts/sort_en_xml.py

- name: Commit sorted file
- name: Commit and push changes
run: |
git config user.name "github-actions"
git config user.email "actions@users.noreply.github.com"
git add languages/en.xml
if ! git diff --quiet; then

if git diff --quiet; then
echo "No changes detected."
else
git add languages/en.xml
git commit -m "chore: sort en.xml alphabetically"
git push
fi
60 changes: 30 additions & 30 deletions languages/en.xml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="PLG_INVENTORY_MANAGER_ACCESS_PREFERENCES">Access permission for plugin preferences</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_PREFERENCES_DESC">Here, in addition to the role "Administrator", you can authorize additional roles for access to the plugin preferences.</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_EDIT">Edit permission for the keeper</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_EDIT_DESC">Here you can allow the keeper to edit specific property fields of an item.</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_EDIT_FIELDS">editable fields by the keeper</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_EDIT_FIELDS_DESC">Here you can specify the specific property fields that can be edited by the keeper of the item.</string>
<string name="PLG_INVENTORY_MANAGER_ADD_DATE">Append date</string>
<string name="PLG_INVENTORY_MANAGER_ADD_DATE_DESC">If a date in the format YYYY-MM-DD is to be added to an export file, the checkmark must be set.</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_PREFERENCES">Access permission for plugin preferences</string>
<string name="PLG_INVENTORY_MANAGER_ACCESS_PREFERENCES_DESC">Here, in addition to the role "Administrator", you can authorize additional roles for access to the plugin preferences.</string>
<string name="PLG_INVENTORY_MANAGER_ADDIN_KEEPER_DESC">This table shows the items managed by you:</string>
<string name="PLG_INVENTORY_MANAGER_ADDIN_LAST_RECEIVER_DESC">This table shows the items lent to you:</string>
<string name="PLG_INVENTORY_MANAGER_ADD_DATE">Append date</string>
<string name="PLG_INVENTORY_MANAGER_ADD_DATE_DESC">If a date in the format YYYY-MM-DD is to be added to an export file, the checkmark must be set.</string>
<string name="PLG_INVENTORY_MANAGER_ALLOW_NEGATIVE_NUMBERS">Allow negative numbers</string>
<string name="PLG_INVENTORY_MANAGER_ALLOW_NEGATIVE_NUMBERS_DESC">If it should be possible to enter negative numbers for fields of type "Number" or "Decimal number", the checkbox must be checked.</string>
<string name="PLG_INVENTORY_MANAGER_BASED_ON">(based on #VAR1#)</string>
Expand All @@ -21,19 +21,22 @@
<string name="PLG_INVENTORY_MANAGER_DATETIME_FORMAT">Date representation</string>
<string name="PLG_INVENTORY_MANAGER_DECIMAL_STEP">Decimal steps</string>
<string name="PLG_INVENTORY_MANAGER_DECIMAL_STEP_DESC">The specification of the decimal steps for fields of type "Decimal number".</string>
<string name="PLG_INVENTORY_MANAGER_DEFAULT_CATEGORY">General</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION">Uninstall</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION_DESC">About the uninstall generated by the plugin entries can be deleted from the database.</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION_FORM_DESC">Choose from the scope of the installation.\n\n***ATTENTION: This routine deletes only the entries in the Admidio database. Program files and the link in the menu will not be deleted! ***</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_ACTORGONLY">Delete only data of the current organization.</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_ALLORG">Delete data in all organizations.</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_CONFIGTABLE_DELETE_NOTPOSSIBLE">- The table #VAR1_BOLD# could not be deleted because it still contains data from another organization or another plug-in.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_DATA_DELETED_IN">- Data in table #VAR1_BOLD# deleted.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_DATA_DELETED_IN_ERROR">- An error occurred while deleting the data in table #VAR1_BOLD#.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_ENDMESSAGE">\nTo completely remove the plugin the program files and the menu entry must be removed.</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_STARTMESSAGE">The following deletions were performed:\n\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_TABLE_DELETED">- Table #VAR1_BOLD# deleted.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_TABLE_DELETE_ERROR">- An error occurred while deleting table #VAR1_BOLD#.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_TABLE_DELETE_NOTPOSSIBLE">- The table #VAR1_BOLD# could not be deleted because it still contains data from another organization.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINST_TABLE_DELETED">- Table #VAR1_BOLD# deleted.\n</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION">Uninstall</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION_DESC">About the uninstall generated by the plugin entries can be deleted from the database.</string>
<string name="PLG_INVENTORY_MANAGER_DEINSTALLATION_FORM_DESC">Choose from the scope of the installation.\n\n***ATTENTION: This routine deletes only the entries in the Admidio database. Program files and the link in the menu will not be deleted! ***</string>
<string name="PLG_INVENTORY_MANAGER_DISABLE_BORROWING">Deactivate borrowing options</string>
<string name="PLG_INVENTORY_MANAGER_DISABLE_BORROWING_DESC">Deactivate the fields and their functions that represent the borrowing and returning of items.</string>
<string name="PLG_INVENTORY_MANAGER_DOCUMENTATION">Documentation</string>
<string name="PLG_INVENTORY_MANAGER_DOCUMENTATION_OPEN">Open documentation</string>
<string name="PLG_INVENTORY_MANAGER_DOCUMENTATION_OPEN_DESC">Allows the documentation of the plugin can be opened (An existing Internet connection is required because the data is located on admidio.org).</string>
Expand All @@ -48,52 +51,52 @@
<string name="PLG_INVENTORY_MANAGER_FORMER_DESC">You can make the item to former. This has the advantage that the data is preserved and you can later always see who has borrowed this item.\n\nIf you select Delete, the record is irrevocably removed from the database and it is no longer possible to view the data of this item.</string>
<string name="PLG_INVENTORY_MANAGER_GENERAL">General filter - Multiple filter terms are to be separated by commas. To exclude words, a - must be placed in front of them. Example: Meier, Huber, -Item case</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT">Import</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_DESC">Here you can import items from a previous export file or your own file.</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_ASSIGN_FIELDS">In the left column of the following table all item fields are displayed. In the right column the columns from the file to be imported are displayed in a selection list. You should now assign all columns from the file you want to import to a item field.</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_DESC">Here you can import items from a previous export file or your own file.</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_ITEMS">Import items</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_PROGRESS">The item #VAR1_BOLD# was imported #VAR2_BOLD#.</string>
<string name="PLG_INVENTORY_MANAGER_IMPORT_UNUSED_HEAD">The following columns of the import file are not assigned to any item fields in InventoryManager:</string>
<string name="PLG_INVENTORY_MANAGER_INVENTORY_MANAGER">InventoryManager</string>
<string name="PLG_INVENTORY_MANAGER_ITEM">Item</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD">Item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDS">Item fields</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDSMANAGE">Maintain itemfields</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDSMANAGE_DESC">Item fields can be created and edited in item field maintenance.</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_CREATE">Create a item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETE">Delete the item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETED">Item field deleted</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETE_DESC">Should this item field and the associated item data be deleted?</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_EDIT">Change the item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMLIST">Item list</string>
<string name="PLG_INVENTORY_MANAGER_ITEMNAME">Item name</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_COPY">Copy the item</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_CREATE">Create a item</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_CREATE_DESC">Individual items can be generated here.\n\nNote: In the "Change the item" view, you can use the "Copy the item" menu item to copy an existing item once or several times.</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_DELETE">Delete the item</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_DELETE_DESC">Should this item be deleted?</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_DELETED">Item deleted</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_DELETE_DESC">Should this item be deleted?</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_EDIT">Change the item</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_MADE_TO_FORMER">Item was made to former</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_PRINT">Print the item</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_UNDO_FORMER">Undo item made to former</string>
<string name="PLG_INVENTORY_MANAGER_ITEM_UNDO_FORMER_DESC">You can reintegrate the item into the inventory management.\n\nIf you select Delete, the record will be irrevocably removed from the database and it will no longer be possible to view the data of this item.</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD">Item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_CREATE">Create a item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETE">Delete the item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETE_DESC">Should this item field and the associated item data be deleted?</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_DELETED">Item field deleted</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELD_EDIT">Change the item field</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDS">Item fields</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDSMANAGE">Maintain itemfields</string>
<string name="PLG_INVENTORY_MANAGER_ITEMFIELDSMANAGE_DESC">Item fields can be created and edited in item field maintenance.</string>
<string name="PLG_INVENTORY_MANAGER_ITEMLIST">Item list</string>
<string name="PLG_INVENTORY_MANAGER_ITEMNAME">Item name</string>
<string name="PLG_INVENTORY_MANAGER_KEEPER">Keeper</string>
<string name="PLG_INVENTORY_MANAGER_KEEPER_FORMER_DESC">You can reintegrate the item into the inventory management. This has the advantage that the data is preserved and you can later always see who has borrowed this item.\n\nIf you want to delete the item, please contact an administrator or the manager of the inventory management!</string>
<string name="PLG_INVENTORY_MANAGER_KEEPER_ITEM_UNDO_FORMER_DESC">You can reintegrate the item into the inventory management.\n\nIf you want to delete the item, please contact an administrator or the manager of the inventory management!</string>
<string name="PLG_INVENTORY_MANAGER_MENU_URL_ERROR">The authorization check of the plugin failed. There is more than one menu item with the same URL defined.\n\n=> #VAR1_BOLD#</string>
<string name="PLG_INVENTORY_MANAGER_MENU_URL_ERROR">The authorization check of the plugin failed. There is more than one menu item with the same URL defined.\n\n=&gt; #VAR1_BOLD#</string>
<string name="PLG_INVENTORY_MANAGER_NAME_OF_PLUGIN">InventoryManager</string>
<string name="PLG_INVENTORY_MANAGER_NEW">New</string>
<string name="PLG_INVENTORY_MANAGER_NO_NEW_IMPORT_DATA">There was no new data in the import file!</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEMS_IMPORTED">The following items were imported by #VAR1_BOLD#:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEM_CHANGED">The item #VAR1_BOLD# was changed by #VAR2_BOLD#:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEM_CREATED">The item #VAR1_BOLD# was created by #VAR2_BOLD#:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEM_DELETED">An item was deleted:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEM_MADE_FORMER">An item was made to former:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_MESSAGE_ITEMS_IMPORTED">The following items were imported by #VAR1_BOLD#:</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEMS_IMPORTED">Items have been imported into the inventory</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEM_CHANGED">An item in the inventory has been changed</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEM_CREATED">An item has been added to the inventory</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEM_DELETED">An item in the inventory has been deleted</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEM_MADE_FORMER">An item in the inventory has been made to former</string>
<string name="PLG_INVENTORY_MANAGER_NOTIFICATION_SUBJECT_ITEMS_IMPORTED">Items have been imported into the inventory</string>
<string name="PLG_INVENTORY_MANAGER_NO_NEW_IMPORT_DATA">There was no new data in the import file!</string>
<string name="PLG_INVENTORY_MANAGER_NUMBER">Number</string>
<string name="PLG_INVENTORY_MANAGER_NUMBER_DESC">Number of items to be added</string>
<string name="PLG_INVENTORY_MANAGER_NUMBER_OF_ITEMS">Number of items</string>
Expand All @@ -118,9 +121,6 @@
<string name="PLG_INVENTORY_MANAGER_USE_CURRENT_USER">Current user as default selection</string>
<string name="PLG_INVENTORY_MANAGER_USE_CURRENT_USER_DESC">If the current user is to be preset as the keeper when adding new items, the checkbox must be checked.</string>
<string name="PLG_INVENTORY_MANAGER_USING_CURRENT_VERSION">You are using the current #VAR1# version of InventoryManager!</string>
<string name="PLG_INVENTORY_MANAGER_DISABLE_BORROWING">Deactivate borrowing options</string>
<string name="PLG_INVENTORY_MANAGER_DISABLE_BORROWING_DESC">Deactivate the fields and their functions that represent the borrowing and returning of items.</string>
<string name="PLG_INVENTORY_MANAGER_DEFAULT_CATEGORY">General</string>
<!-- Phrases only in Database -->
<string name="PIM_CATEGORY">Category</string>
<string name="PIM_CATEGORY_DESCRIPTION">Category of the item</string>
Expand All @@ -136,4 +136,4 @@
<string name="PIM_RECEIVED_BACK_ON_DESCRIPTION">The date the item was returned to the keeper</string>
<string name="PIM_RECEIVED_ON">lent on</string>
<string name="PIM_RECEIVED_ON_DESCRIPTION">The lending date of the item to the last recipient</string>
</resources>
</resources>
Loading