Compare commits

..

4 Commits

Author SHA1 Message Date
Hosted Weblate 5efd153908 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 79.3% (335 of 422 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: ??? <2807603108@qq.com>
Translate-URL: https://hosted.weblate.org/projects/tagstudio/strings/zh_Hans/
Translation: TagStudio/Application Strings
2026-07-21 15:01:26 +02:00
Hosted Weblate e106e9759c Translated using Weblate (French)
Currently translated at 100.0% (422 of 422 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Med <45147847+kitsumed@users.noreply.github.com>
Translate-URL: https://hosted.weblate.org/projects/tagstudio/strings/fr/
Translation: TagStudio/Application Strings
2026-07-21 15:01:25 +02:00
Hosted Weblate 5c282e0ada Translated using Weblate (Spanish)
Currently translated at 100.0% (422 of 422 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (422 of 422 strings)

Co-authored-by: 2004milenadiaz-source <2004.milena.diaz@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Julen Arratibel Etxabe <jarratibeletxabe@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/tagstudio/strings/es/
Translation: TagStudio/Application Strings
2026-07-21 15:01:25 +02:00
Hosted Weblate de1d8e5c1b Translated using Weblate (Hungarian)
Currently translated at 100.0% (423 of 423 strings)

Co-authored-by: Szíjártó Levente Pál <szijartoleventepal@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/tagstudio/strings/hu/
Translation: TagStudio/Application Strings
2026-07-21 15:01:24 +02:00
13 changed files with 165 additions and 304 deletions
+16 -6
View File
@@ -117,7 +117,7 @@ Licensing is now accomplished using the [REUSE](https://reuse.software/spec-3.3/
!!! tip "PR Scope"
If you're unsure where to stop the scope of your PR, ask yourself: _"If I broke this up, could any parts of it still be used by the project in the meantime?"_
### :material-check-circle: Workflow Checks
### Workflow Checks
When pushing your code, several automated [workflows](https://github.com/TagStudioDev/TagStudio/tree/main/.github/workflows) will check it against predefined tests and style checks. It's _highly recommended_ that you run these checks locally beforehand to avoid having to fight back-and-forth with the workflow checks inside your pull requests. These checks currently include:
@@ -126,7 +126,7 @@ When pushing your code, several automated [workflows](https://github.com/TagStud
- [Pytest](developing.md#pytest) tests
- REUSE [license compliance](#licenses)
## :material-timer-play: Runtime Requirements
### Runtime Requirements
Code must function on all of the supported operating systems and versions:
@@ -134,8 +134,18 @@ Code must function on all of the supported operating systems and versions:
- macOS 14.0+
- Common Linux distributions and versions
Final submitted code must **_NOT:_**
## :material-file-document: Documentation Guidelines
- Contain superfluous or unnecessary logging statements
- Cause unreasonable slowdowns to the program outside of a progress-indicated task
- Cause undesirable visual glitches or artifacts on screen
Documentation contributions include anything inside of the `docs/` folder as well as the `README.md`. Documentation inside the `docs/` folder is built and hosted on our static documentation site, [docs.tagstud.io](https://docs.tagstud.io/).
- Use "[dash-case / kebab-case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case)" for file and folder names
- Follow the folder structure pattern
- Don't add images or other media with excessively large file sizes
- Provide alt text for embedded media
- Use "[Title Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case)" for title capitalization
## :material-translate: Translation Guidelines
Translations are performed on the TagStudio [Weblate project](https://hosted.weblate.org/projects/tagstudio/).
_Translation guidelines coming soon._
+2 -2
View File
@@ -118,7 +118,7 @@ If you choose to manually set up a virtual environment and install dependencies
!!! Warning "Linux Library Dependencies"
If developing TagStudio on Linux, certain libraries are required that may not be included with your distribution. A full list of these can be found [here](install.md#linux).
## Nix & NixOS
## Nix(OS)
If using [Nix](https://nixos.org/), there is a development environment already provided in the [flake](https://wiki.nixos.org/wiki/Flakes) that is accessible with the following command:
@@ -214,7 +214,7 @@ From there, Git will automatically run through the hooks during commit actions!
You can automatically enter this development shell, and keep your user shell, with a tool like [direnv](https://direnv.net/). Some reference `.envrc` files are provided in the repository at [`contrib`](https://github.com/TagStudioDev/TagStudio/tree/main/contrib).
Two currently available are for [Nix](#nix-nixos) and [uv](#installing-with-uv), to use one:
Two currently available are for [Nix](#nixos) and [uv](#installing-with-uv), to use one:
```sh
ln -s .envrc-$variant .envrc
+2 -2
View File
@@ -27,12 +27,12 @@ hide:
![TagStudio screenshot](./assets/tag_bubbles.png)
<span style="font-family: Bai Jamjuree, Roboto, sans-serif; font-size: 1.1rem; letter-spacing: -0.05rem;"><span style="font-weight: 900;">Tag</span><span style="font-weight: 500;"><i>Studio</i></span></span> is a photo & file organization application with an underlying tag-based system that focuses on giving freedom and flexibility to the user. No proprietary programs or formats, no sea of sidecar files, and no complete upheaval of your filesystem structure.
**TagStudio** is a photo & file organization application with an underlying tag-based system that focuses on giving freedom and flexibility to the user. No proprietary programs or formats, no sea of sidecar files, and no complete upheaval of your filesystem structure.
</div>
<figure markdown="span">
[:material-github: Download Latest Release](https://github.com/TagStudioDev/TagStudio/releases){ .md-button .md-button--primary }
[:material-download: Download Latest Release](https://github.com/TagStudioDev/TagStudio/releases){ .md-button .md-button--primary }
</figure>
## :material-star: Core Features
+3 -3
View File
@@ -95,9 +95,9 @@ Some external dependencies are required for TagStudio to execute. Below is a tab
Aborted (core dumped)
```
### :material-nix: Nix & NixOS
### :material-nix: Nix(OS)
For [Nix](https://nixos.org/), the TagStudio repository includes a [flake](https://wiki.nixos.org/wiki/Flakes) that provides some outputs such as a development shell and package.
For [Nix(OS)](https://nixos.org/), the TagStudio repository includes a [flake](https://wiki.nixos.org/wiki/Flakes) that provides some outputs such as a development shell and package.
Two packages are provided: `tagstudio` and `tagstudio-jxl`. The distinction was made because `tagstudio-jxl` has an extra compilation step for [JPEG-XL](https://jpeg.org/jpegxl) image support. To give either of them a test run, you can execute `nix run github:TagStudioDev/TagStudio#tagstudio`. If you are in a cloned repository and wish to run a package with the context of the repository, you can simply use `nix run` with no arguments.
@@ -256,4 +256,4 @@ To generate thumbnails for RAR-based files (like `.cbr`) you'll need an extracto
### ripgrep
A recommended tool to improve the performance of directory scanning is [ripgrep](https://github.com/BurntSushi/ripgrep), a Rust-based directory walker that natively integrates with our [`.ts_ignore`](ignore.md) (`.gitignore`-style) pattern matching system for excluding files and directories. Ripgrep is already pre-installed on some Linux distributions and also available from several package managers.
A recommended tool to improve the performance of directory scanning is [`ripgrep`](https://github.com/BurntSushi/ripgrep), a Rust-based directory walker that natively integrates with our [`.ts_ignore`](ignore.md) (`.gitignore`-style) pattern matching system for excluding files and directories. Ripgrep is already pre-installed on some Linux distributions and also available from several package managers.
+88 -179
View File
@@ -6,207 +6,116 @@ icon: material/sign-text
<!-- SPDX-FileCopyrightText: (c) TagStudio Contributors -->
<!-- SPDX-License-Identifier: GPL-3.0-only -->
<!-- prettier-ignore -->
!!! abstract "Prerequisite Reading"
This guide assumes you've read the [Developing](developing.md) and [Contributing](contributing.md) pages first.
# :material-sign-text: Style Guide
## :material-script-text: General Principles
## Formatting
- Write **clear**, **concise**, and **modular** code.
- If the purpose of a peice of code is not obvious, a **short comment** should help explain it.
- Remember to follow the rest of the [contribution guidelines](contributing.md)!
Most of the style guidelines can be checked, fixed, and enforced via Ruff. Older code may not be adhering to all of these guidelines, in which case _"do as I say, not as I do"..._
---
- Do your best to write clear, concise, and modular code.
- This should include making methods private by default (e.g. `__method()`)
- Methods should only be protected (e.g. `_method()`) or public (e.g. `method()`) when needed and warranted
- Keep a maximum column width of no more than **100** characters.
- Code comments should be used to help describe sections of code that can't speak for themselves.
- Use [Google style](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings) docstrings for any classes and functions you add.
- If you're modifying an existing function that does _not_ have docstrings, you don't _have_ to add docstrings to it... but it would be pretty cool if you did ;)
- Imports should be ordered alphabetically.
- Lists of values should be ordered using their [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order).
- Some files have their methods ordered alphabetically as well (i.e. [`thumb_renderer`](https://github.com/TagStudioDev/TagStudio/blob/main/src/tagstudio/qt/widgets/thumb_renderer.py)). If you're working in a file and notice this, please try and keep to the pattern.
- When writing text for window titles or form titles, use "[Title Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case)" capitalization. Your IDE may have a command to format this for you automatically, although some may incorrectly capitalize short prepositions. In a pinch you can use a website such as [capitalizemytitle.com](https://capitalizemytitle.com/) to check.
- If it wasn't mentioned above, then stick to [**PEP-8**](https://peps.python.org/pep-0008/)!
## :material-text-box-check: Formatting
### Modules & Implementations
Linting in Python files is mostly taken care of by [ruff](developing.md#ruff) and is based on the rules declared in `pyproject.toml` and `.editorconfig`.
- **Do not** modify legacy library code in the `src/core/library/json/` directory
- Avoid direct calls to `os`
- Use `Pathlib` library instead of `os.path`
- Use `platform.system()` instead of `os.name` and `sys.platform`
- Don't prepend local imports with `tagstudio`, stick to `src`
- Use the `logger` system instead of `print` statements
- Avoid nested f-strings
- Use HTML-like tags inside Qt widgets over stylesheets where possible
Final submitted code must **_NOT:_**
- Contain superfluous or unnecessary logging statements
- Cause unreasonable slowdowns to the program outside of a progress-indicated task
- Cause undesirable visual glitches or artifacts on screen
### Formatter Configs
TagStudio provides an [EditorConfig](https://editorconfig.org/#example-file) file ([`.editorconfig`](https://github.com/TagStudioDev/TagStudio/blob/main/.editorconfig)) along with a [Prettier](https://prettier.io/) config file ([`.prettierrc.toml`](https://github.com/TagStudioDev/TagStudio/blob/main/.prettierrc.toml)) for formatting files other than .py files (Markdown, JSON, YAML, HTML, CSS, etc.). If editing these types of files it's recommended that you use a formatter that supports EditorConfig or has its settings matched to the EditorConfig and Prettier configs. Lastly, please pay attention to the `prettier-ignore` flags in present in some files if you are not using Prettier, as formatting these sections will break formatting used elsewhere such as the [MkDocs site](https://docs.tagstud.io/).
### :material-code-braces-box: Syntax Guidelines
## Qt
- Python files should always follow the [**PEP 8**]() style guide conventions, unless specifically allowed otherwise.
- The most notable exception in our project is the line length limit of **100** characters, which is enforced via ruff.
- Internal Qt methods also use `camelCase` instead of `snake_case`, so overrides of those are commonly seen in the codebase.
- Classes and attributes considered to be "[private](https://docs.python.org/3/tutorial/classes.html#private-variables)" should be prepended with a **single underscore** (e.g. `_internal_method()`).
- If _functionally necessary_, an attribute name may be prepended with a double underscore to trigger "[name mangling](https://docs.python.org/3/reference/expressions.html#private-name-mangling)" (e.g. `__mangled_method()`).
- Classes and methods should contain [Google style](https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings) docstrings _(this style is enforced via ruff)_.
- Lists and JSON keys should be ordered by their [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order) unless otherwise specified or readily indicated.
- Some files have some or all of their attributes sorted. Please respect any established patterns like these in files you modify.
As of writing this section, the QT part of the code base is quite unstructured and the View and Controller parts are completely intermixed[^1]. This makes maintenance, fixes and general understanding of the code base quite challenging, because the interesting parts you are looking for are entangled in a bunch of repetitive UI setup code. To address this we are aiming to more strictly separate the view and controller aspects of the QT frontend.
---
The general structure of the QT code base should look like this:
## :material-filter-cog: Modules & Systems
### :fontawesome-brands-python: Python Modules
- Use `Pathlib` library instead of `os.path`
- Use `platform.system()` instead of `os.name` or `sys.platform`
- Avoid nested f-strings
### :material-tag: TagStudio Systems
- Translation keys can be accessed via bracket notation (e.g. `Translations["translation_key"]`) or with the `Translations.format()` method when a value needs to be passed to a placeholder in the translation.
- Avoid passing around the `QtDriver` class where possible. Instead, pass only the necessary components such as the `Library` and `GlobalSettings` instances.
- Use HTML-like tags inside strings over explicit stylesheets where possible. The `Style` class provides several handy methods for formatting text with these.
- Use the `format` method in the stylesheets class to format text headers.
---
## :material-folder-file: Project Layout
### :material-engine: Core <small>Backend</small>
Code that is integral to the core functionality of TagStudio and is UI-independent belongs under the `core/` directory. It's possible that some code that serves the UI can go here, as long as its purpose is to serve _any_ UI and is independent from Qt (e.g. file preview rendering).
```yaml title="Core Backend Directory Example"
core/
├── library/ # The TagStudio library system
│ │
│ ├── alchemy/ # Current SQLite backend w/ SQLAlchemy ORM
│ │
│ ├── json/ # Read-only legacy JSON library system, kept for migrations
│ │
│ ├── query_lang/ # The query parser
│ │
│ │ # Library files that do not involve the SQLAlchemy ORM
│ │ # NOTE: Future Non-SQLAlchemy library files will be placed here
│ ├── refresh.py
│ └── ...
└── utils/ # Utility classes and functions for the core
```
qt
├── controllers
│ ├── widgets
│ │ └── preview_panel_controller.py
│ └── main_window_controller.py
├── views
│ ├── widgets
│ │ └── preview_panel_view.py
│ └── main_window_view.py
├── ts_qt.py
└── mixed.py
```
<!-- prettier-ignore -->
!!! danger "Read-Only Legacy Code"
**Do not modify** legacy library code in the `src/core/library/json/` directory!
In this structure there are the `views` and `controllers` sub-directories. They have the exact same structure and for every `<component>_view.py` there is a `<component>_controller.py` at the same location in the other subdirectory and vice versa.
---
Typically the classes should look like this:
### :material-button-cursor: App UI <small>Frontend</small>
```py
# my_cool_widget_view.py
class MyCoolWidgetView(QWidget):
def __init__(self):
super().__init__()
self.__button = QPushButton()
self.__color_dropdown = QComboBox()
# ...
self.__connect_callbacks()
The application UI code is stored in the `qt/` directory, and contains all code specific to the Qt frontend. Qt widgets are built using an [MVC](https://www.geeksforgeeks.org/software-engineering/mvc-framework-introduction/) pattern, which is described in-depth below:
def __connect_callbacks(self):
self.__button.clicked.connect(self._button_click_callback)
self.__color_dropdown.currentIndexChanged.connect(
lambda idx: self._color_dropdown_callback(self.__color_dropdown.itemData(idx))
)
#### MVC Pattern
- **Models** are usually just objects from the [library](#core-backend).
- The **controller** interacts with these, the _view_ does **not**.
- **Views** are Qt layout classes that **_only_** contain the **layout** and **styling** for one or more widgets.
- Class names are appended with `View`, and filenames appended with `_view`.
- Not to be used standalone, but as the layouts for one or more controllers.
- Some logic is acceptable in these classes if it serves to modularize the layout and allows controllers to influence how the layout is initialized.
- **Reusable Layouts**
- If a layout class is **_not meant_** to act as a view but instead be a generic layout, it belongs in the `views/layouts/` directory and the file should be appended with `_layout`.
- **Styling Classes**
- If a class is purely a source of reusable styling, it belongs in the `views/styles/` directory.
- **Controllers** are complete widgets or base classes for complete widgets.
- Controller files simply take on the name of the final widget they create.
- This also creates naming parity with other widgets that simply extend existing Qt widgets with additional logic.
```yaml title="Qt Frontend Directory Example"
qt/
├── controllers/ # Widgets implementing views or extending other widgets
│ ├── tag_suggest_box.py # Extends from `suggest_box.py`
│ ├── suggest_box.py # Implements `suggest_box_view.py`
│ ├── main_window.py
│ └── ...
├── mixed/ # Files yet to be refactored into controllers and views
├── views/ # Everything related to widget layouts and appearances
│ │
│ ├── layouts/ # Layouts meant to be reused on their own inside other layouts
│ │ ├── flow_layout.py
│ │ └── ...
│ │
│ ├── styles/ # Classes specific for styling
│ │ ├── palette.py
│ │ ├── stylesheets.py
│ │ └── ...
│ │
│ │ # Views (layouts) that get implemented by controllers (widgets)
│ ├── main_window_view.py
│ ├── suggest_box_view.py
│ └── ...
│ # Frontend classes that aren't related to widgets, like managers
├── resource_manager.py
├── cache_manager.py
├── ts_qt.py # Qt Driver
└── ...
def _button_click_callback(self):
raise NotImplementedError()
```
<!-- prettier-ignore -->
!!! warning "Pre-MVC UI Code"
**Do not add** new files to the `qt/mixed/` directory! These files have yet to to be refactored per the current MVC style guidelines and the directory will be **removed** once those migrations have concluded.
```py
# my_cool_widget_controller.py
class MyCoolWidget(MyCoolWidgetView):
def __init__(self):
super().__init__()
Observe the following key aspects of the example below:
def _button_click_callback(self):
print("Button was clicked!")
- The **view** extends from a Qt layout class, and the **controller** simply extends from QWidget.
- The **controller** is just called `MyCoolWidget` instead of `MyCoolWidgetController` as it will be directly used by other code.
- The **view's** widgets that are intended to be controlled by the controller are **public**, while the **controller's** methods are largely **private**.
def _color_dropdown_callback(self, color: Color):
print(f"The selected color is now: {color}")
```
Observe the following key aspects of this example:
- The Controller is just called `MyCoolWidget` instead of `MyCoolWidgetController` as it will be directly used by other code
- The UI elements are in private variables
- This enforces that the controller shouldn't directly access UI elements
- Instead the view should provide a protected API (e.g. `_get_color()`) for things like setting/getting the value of a dropdown, etc.
- Instead of `_get_color()` there could also be a `_color` method marked with `@property`
- The callback methods are already defined as protected methods with NotImplementedErrors
- Defines the interface the callbacks
- Enforces that UI events be handled
<!-- prettier-ignore -->
!!! example "MVC-Separated Widget Example"
!!! tip
A good (non-exhaustive) rule of thumb is: If it requires a non-UI import, then it doesn't belong in the `*_view.py` file.
```py title="views/my_cool_widget_view.py"
class MyCoolWidgetView(QVBoxLayout):
def __init__(self):
super().__init__()
self.button = QPushButton()
self.color_dropdown = QComboBox()
self.addWidget(self.button)
self.addWidget(self.color_dropdown)
```
```py title="controllers/my_cool_widget.py"
class MyCoolWidget(QWidget):
def __init__(self):
super().__init__()
self.setLayout(MyCoolWidgetView())
self._connect_callbacks()
def _connect_callbacks(self):
self.layout().button.clicked.connect(self._button_click_callback)
self.layout().color_dropdown.currentIndexChanged.connect(
lambda idx: self._color_dropdown_callback(self.color_dropdown.itemData(idx)))
def _button_click_callback(self):
print("Button was clicked!")
def _color_dropdown_callback(self, color: Color):
print(f"The selected color is now: {color}")
```
<!-- prettier-ignore -->
!!! tip "Tip for Logic Placement"
A good rule of thumb is: If there's **conditional logic** after a widget has been created, it should probably go in a **controller**.
---
## :material-file-document: Documentation
Documentation contributions include anything inside the `docs/` folder as well as the `README.md`. Documentation inside the `docs/` folder is built and hosted on our static documentation site, [docs.tagstud.io](https://docs.tagstud.io/). Some files such as the `CHANGELOG.md`, `CONTRIBUTING.md`, and `STYLE.md` are symlinked in the repo root from the `docs/` folder.
- Use "[dash-case / kebab-case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case)" for file and folder names
- Follow the folder structure pattern
- Don't add images or other media with excessively large file sizes
- Provide alt text for embedded media
- Use "[Title Case](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case)" for title capitalization
---
## :material-translate: Translations
Translations are performed on the TagStudio [Weblate project](https://hosted.weblate.org/projects/tagstudio/).
- Do not change text inside placeholders
- Do not change the style tags inside translations
- Use the glossary for term definitions
[^1]: For an explanation of the Model-View-Controller (MVC) Model, checkout this article: [MVC Framework Introduction](https://www.geeksforgeeks.org/mvc-framework-introduction/).
+2 -69
View File
@@ -3,14 +3,11 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
/* Dark Theme */
[data-md-color-scheme="slate"] {
--md-primary-fg-color: rgb(197, 110, 255);
--md-accent-fg-color: rgb(92, 222, 255);
--md-default-bg-color: #060617;
--md-default-fg-color: #eae1ff;
--md-default-fg-color--light: #c2a5ff;
--md-code-fg-color: #d8c7ffcc;
--md-default-fg-color--light: #b898ff;
--md-code-fg-color: #eae1ffcc;
--md-code-hl-string-color: rgb(92, 255, 228);
--md-code-hl-keyword-color: rgb(61, 155, 255);
--md-code-hl-constant-color: rgb(205, 78, 255);
@@ -20,8 +17,6 @@
/* Light Theme */
[data-md-color-scheme="default"] {
--md-primary-fg-color: #7758ff;
--md-accent-fg-color: rgb(22, 166, 255);
--md-default-fg-color--light: #090a26;
}
@@ -78,11 +73,6 @@ td {
padding: 0.5em 1em 0.5em 1em !important;
}
hr {
border-bottom-width: 2px !important;
border-color: #9988ff50 !important;
}
.md-typeset ul li ul {
margin-top: 0;
margin-bottom: 0.1rem;
@@ -129,18 +119,6 @@ h2,
margin-right: -0.8rem;
}
.md-code__nav,
.md-content__button,
.headerlink {
border-radius: 0.2rem;
background: none;
color: #9988ff50 !important;
}
.md-code__nav:hover {
background-color: #9988ff50;
}
figcaption {
margin-top: 0 !important;
}
@@ -171,51 +149,6 @@ td code {
padding: 0 !important;
}
.admonition {
border-radius: 0.4rem !important;
border-width: 2px !important;
}
.highlight > .filename {
border-width: 2px !important;
border: solid;
border-color: #9988ff10 !important;
border-radius: 0.4rem 0.4rem 0 0 !important;
}
code {
border-radius: 0.4rem !important;
border-width: 2px !important;
border: solid;
border-color: #9988ff10;
}
:is(span, ul, li, td, p, a) > code {
border-width: 1px !important;
border-radius: 0.1rem !important;
}
.filename + pre > code {
border-top-width: 0 !important;
border-radius: 0 0 0.4rem 0.4rem !important;
}
.tabbed-labels.tabbed-labels--linked {
padding-left: 0.4rem;
padding-right: 0.4rem;
box-shadow: none !important;
}
.admonition-title {
font-size: 0.7rem;
font-family: "Bai Jamjuree", Roboto, sans-serif;
font-weight: 600 !important;
}
.admonition-title span {
margin-top: 0.05rem !important;
}
/* Matches the palette used by mkdocs-material */
.priority-high {
color: #f1185a;
-27
View File
@@ -29,30 +29,3 @@ h2 {
margin-right: 0;
}
}
.grid.cards > ul > li {
border-radius: 0.4rem !important;
border-width: 2px !important;
border-color: #9988ff20 !important;
}
.md-button--primary {
margin: 1rem;
padding: 0.3rem 1.2rem !important;
border-radius: 0.4rem !important;
font-size: 1rem;
font-family: "Bai Jamjuree", Roboto, sans-serif;
background: linear-gradient(60deg, rgb(205, 78, 255) 0%, rgb(116, 123, 255) 100%);
border-style: solid;
border-width: 0 0 2px 0 !important;
border-color: #ffffff33 !important;
}
.md-button--primary:hover {
background: linear-gradient(60deg, rgb(205, 78, 255) 30%, rgb(116, 123, 255) 100%);
border-color: #ffffff55 !important;
}
.md-button--primary span {
margin-top: 0.1rem !important;
}
+4 -4
View File
@@ -70,16 +70,16 @@ theme:
# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
primary: custom
accent: custom
primary: purple
accent: purple
toggle:
icon: material/lightbulb
name: Switch to Dark Mode
# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: custom
accent: custom
primary: purple
accent: purple
toggle:
icon: material/lightbulb-night-outline
name: Switch to System Preference
@@ -1728,8 +1728,6 @@ class Library:
session.flush()
if aliases is not None:
for a in aliases:
a.tag_id = tag.id
self.update_aliases(tag, aliases, session)
session.flush()
+10 -10
View File
@@ -1,5 +1,5 @@
{
"about.app_cache_path": "Ruta caché aplicación",
"about.app_cache_path": "Ruta de la Caché de la Aplicación",
"about.config_path": "Ruta de Configuración",
"about.description": "TagStudio es una aplicación para organizar fotografías y archivos que utiliza un sistema de etiquetas subyacentes centrado en dar libertad y flexibilidad al usuario. Sin programas ni formatos propios, ni un mar de archivos y sin trastornar completamente la estructura de tu sistema de archivos.",
"about.documentation": "Documentación",
@@ -8,14 +8,14 @@
"about.title": "Acerca de TagStudio",
"about.version": "Versión",
"about.version.latest": "{built_version} (Última versión: {latest_version})",
"about.website": "Página web",
"about.website": "Página Web",
"app.git": "Commit de Git",
"app.pre_release": "Pre-Lanzamiento",
"app.title": "{base_title} - Biblioteca '{library_dir}'",
"color.color_border": "Usar color secundario para el Borde",
"color.color_border": "Usar Color Secundario para Borde",
"color.confirm_delete": "¿Estás seguro de que quieres eliminar el color \"{color_name}\"?",
"color.delete": "Eliminar Etiqueta",
"color.import_pack": "Importar paquete de colores",
"color.import_pack": "Importar Paquete de Colores",
"color.name": "Nombre",
"color.namespace.delete.prompt": "¿Estás seguro de que quieres eliminar el espacio de nombres de este color? ¡Esto eliminará todos los colores en el espacio de nombres junto con él!",
"color.namespace.delete.title": "Eliminar el espacio de nombres de color",
@@ -25,7 +25,7 @@
"color.primary_required": "Color primario (Obligatorio)",
"color.secondary": "Color secundario",
"color.title.no_color": "Sin color",
"color_manager.title": "Administrar los colores de las etiquetas",
"color_manager.title": "Administrar Colores de Etiquetas",
"dependency.missing.title": "{dependency} no encontrada",
"drop_import.description": "Los siguientes archivos igualan con las rutas de archivos que ya existen en la biblioteca",
"drop_import.duplicates_choice.plural": "Los siguientes {count} archivos igualan con las rutas de archivos que ya existen en la biblioteca.",
@@ -227,12 +227,12 @@
"language.tr": "Turco",
"language.zh_Hans": "Chino (simplificado)",
"language.zh_Hant": "Chino (tradicional)",
"library.missing": "Falta la ubicación",
"library.missing": "Falta la Ubicación de la Biblioteca",
"library.name": "Biblioteca",
"library.refresh.scanning.plural": "Escaneando directorios en busca de nuevos archivos...\n{searched_count} archivos buscados, {found_count} nuevos archivos encontrados",
"library.refresh.scanning.singular": "Escaneando directorios en busca de nuevos archivos...\n{searched_count} Archivos buscados, {found_count} Nuevos archivos encontrados",
"library.refresh.scanning_preparing": "Buscar archivos nuevos en los directorios...\nPreparando...",
"library.refresh.title": "Refrescar directorios",
"library.refresh.scanning_preparing": "Buscando archivos nuevos en los directorios...\nPreparando...",
"library.refresh.title": "Refrescando directorios",
"library.scan_library.title": "Escaneando la biblioteca",
"library_info.cleanup": "Limpieza",
"library_info.cleanup.backups": "Reespaldos de la Librería:",
@@ -387,7 +387,7 @@
"tag.is_category": "Es categoría",
"tag.is_hidden": "Está oculto",
"tag.name": "Nombre",
"tag.new": "Nueva etiqueta",
"tag.new": "Nueva Etiqueta",
"tag.parent_tags": "Etiquetas principales",
"tag.parent_tags.add": "Añadir etiquetas principales",
"tag.parent_tags.description": "Esta etiqueta se puede tratar como sustituto de cualquiera de las etiquetas padre en las búsquedas.",
@@ -417,7 +417,7 @@
"view.size.1": "Pequeño",
"view.size.2": "Medio",
"view.size.3": "Grande",
"view.size.4": "Extra grande",
"view.size.4": "Extra Grande",
"window.message.error_opening_library": "Error abriendo la biblioteca.",
"window.title.error": "Error",
"window.title.open_create_library": "Abrir/Crear biblioteca"
@@ -4,6 +4,7 @@
"about.description": "TagStudio est une application d'organisation de photos et de fichiers avec un système de tags qui met en avant la liberté et flexibilité à l'utilisateur. Pas de programmes ou de formats propriétaires, pas la moindre trace de fichiers secondaires, et pas de bouleversement complet de la structure de votre système de fichiers.",
"about.documentation": "Documentation",
"about.module.found": "Trouvé",
"about.modules.title": "Modules optionnels",
"about.title": "À propos de TagStudio",
"about.version": "Version",
"about.version.latest": "{built_version} (Dernière version : {latest_version})",
@@ -196,6 +197,36 @@
"json_migration.title.new_lib": "<h2>Bibliothèque v9.5+</h2>",
"json_migration.title.old_lib": "<h2>Bibliothèque v9.4</h2>",
"landing.open_create_library": "Ouvrir/Créer une Bibliothèque {shortcut}",
"language.am": "Amharic",
"language.ceb": "Cébuano",
"language.cs": "Tchèque",
"language.da": "Danois",
"language.de": "Allemand",
"language.el": "Grec",
"language.en": "Anglais",
"language.es": "Espagnol",
"language.fi": "Finnois",
"language.fil": "Philippin",
"language.fr": "Français",
"language.hu": "Hongrois",
"language.is": "Islandais",
"language.it": "Italien",
"language.ja": "Japonais",
"language.nb_NO": "Norvégien (Bokmål)",
"language.nl": "Néerlandais",
"language.pl": "Polonais",
"language.pt": "Portugais",
"language.pt_BR": "Portugais (Brésil)",
"language.qpv": "Viossa",
"language.ro": "Roumain",
"language.ru": "Russe",
"language.sv": "Suédois",
"language.ta": "Tamil",
"language.th": "Thaï",
"language.tok": "Toki Pona",
"language.tr": "Turc",
"language.zh_Hans": "Chinois (Simplifier)",
"language.zh_Hant": "Chinois (Traditionnelle)",
"library.missing": "Emplacement Manquant",
"library.name": "Bibliothèque",
"library.refresh.scanning.plural": "Analyse du Répertoire pour de Nouveaux Fichiers...\n{searched_count} Fichiers Trouvées, {found_count} Nouveaux Fichiers",
@@ -277,6 +308,8 @@
"select.all": "Tout Sélectionner",
"select.clear": "Effacer la Sélection",
"select.inverse": "Inverser la Sélection",
"settings.appearance": "Apparence",
"settings.cached_thumb_resolution.label": "Résolution des vignettes mises en cache",
"settings.clear_thumb_cache.title": "Effacer le cache des vignettes",
"settings.dateformat.english": "Anglais",
"settings.dateformat.international": "International",
@@ -292,6 +325,8 @@
"settings.infinite_scroll": "Défilement continu",
"settings.language": "Langage",
"settings.library": "Paramètres de la Bibliothèque",
"settings.localization": "Localisation",
"settings.media": "Médias",
"settings.open_library_on_start": "Ouvrir la Bibliothèque au Démarrage",
"settings.page_size": "Entités par page",
"settings.restart_required": "Veuillez redémarré TagStudio pour que les changements prenne effet.",
@@ -10,6 +10,7 @@
"about.version.latest": "{built_version} (legújabb kiadás: {latest_version})",
"about.website": "Honlap",
"app.git": "Git-véglegesítés",
"app.nightly": "Napi",
"app.pre_release": "Kísérleti verzió",
"app.title": "{base_title} Könyvtár: „{library_dir}”",
"color.color_border": "Másodlagos szín használata keretszínként",
@@ -1,9 +1,11 @@
{
"about.app_cache_path": "TagStudio缓存路径",
"about.config_path": "配置路径",
"about.description": "TagStudio是一款照片和文件组织应用程序,采用基于标签的系统,旨在为用户提供自由和灵活性。该应用程序不使用专有程序或格式,不会产生大量的辅助文件,也不会对您的文件系统结构造成彻底的颠覆。",
"about.documentation": "文档",
"about.module.found": "存在",
"about.title": "关于 TagStudio",
"about.version": "版本",
"about.website": "网站",
"app.git": "Git 提交更新",
"app.pre_release": "预发布版本",