mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge branch 'dev'
This commit is contained in:
		
							
								
								
									
										46
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -20,7 +20,7 @@ jobs: | |||||||
|         name: Set up Python |         name: Set up Python | ||||||
|         uses: actions/setup-python@v2 |         uses: actions/setup-python@v2 | ||||||
|         with: |         with: | ||||||
|           python-version: 3.8 |           python-version: 3.7 | ||||||
|       - |       - | ||||||
|         name: Get pip cache dir |         name: Get pip cache dir | ||||||
|         id: pip-cache |         id: pip-cache | ||||||
| @@ -49,6 +49,39 @@ jobs: | |||||||
|           name: documentation |           name: documentation | ||||||
|           path: docs/_build/html/ |           path: docs/_build/html/ | ||||||
|  |  | ||||||
|  |   codestyle: | ||||||
|  |     runs-on: ubuntu-20.04 | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v2 | ||||||
|  |       - | ||||||
|  |         name: Set up Python | ||||||
|  |         uses: actions/setup-python@v2 | ||||||
|  |         with: | ||||||
|  |           python-version: 3.7 | ||||||
|  |       - | ||||||
|  |         name: Get pip cache dir | ||||||
|  |         id: pip-cache | ||||||
|  |         run: | | ||||||
|  |           echo "::set-output name=dir::$(pip cache dir)" | ||||||
|  |       - | ||||||
|  |         name: Persistent Github pip cache | ||||||
|  |         uses: actions/cache@v2 | ||||||
|  |         with: | ||||||
|  |           path: ${{ steps.pip-cache.outputs.dir }} | ||||||
|  |           key: ${{ runner.os }}-pip${{ matrix.python-version }} | ||||||
|  |       - | ||||||
|  |         name: Install dependencies | ||||||
|  |         run: | | ||||||
|  |           pip install --upgrade pipenv | ||||||
|  |           pipenv install --system --dev --ignore-pipfile | ||||||
|  |       - | ||||||
|  |         name: Codestyle | ||||||
|  |         run: | | ||||||
|  |           cd src/ | ||||||
|  |           pycodestyle | ||||||
|  |  | ||||||
|   tests: |   tests: | ||||||
|     runs-on: ubuntu-20.04 |     runs-on: ubuntu-20.04 | ||||||
|     strategy: |     strategy: | ||||||
| @@ -76,7 +109,7 @@ jobs: | |||||||
|           path: ${{ steps.pip-cache.outputs.dir }} |           path: ${{ steps.pip-cache.outputs.dir }} | ||||||
|           key: ${{ runner.os }}-pip${{ matrix.python-version }} |           key: ${{ runner.os }}-pip${{ matrix.python-version }} | ||||||
|       - |       - | ||||||
|         name: Prepare tests |         name: Install dependencies | ||||||
|         run: | |         run: | | ||||||
|           sudo apt-get update -qq |           sudo apt-get update -qq | ||||||
|           sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng |           sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng | ||||||
| @@ -87,11 +120,6 @@ jobs: | |||||||
|         run: | |         run: | | ||||||
|           cd src/ |           cd src/ | ||||||
|           pytest |           pytest | ||||||
|       - |  | ||||||
|         name: Codestyle |  | ||||||
|         run: | |  | ||||||
|           cd src/ |  | ||||||
|           pycodestyle |  | ||||||
|       - |       - | ||||||
|         name: Publish coverage results |         name: Publish coverage results | ||||||
|         if: matrix.python-version == '3.8' |         if: matrix.python-version == '3.8' | ||||||
| @@ -130,7 +158,7 @@ jobs: | |||||||
|         path: src/documents/static/frontend/ |         path: src/documents/static/frontend/ | ||||||
|  |  | ||||||
|   build-release: |   build-release: | ||||||
|     needs: [frontend, documentation, tests] |     needs: [frontend, documentation, tests, codestyle] | ||||||
|     runs-on: ubuntu-20.04 |     runs-on: ubuntu-20.04 | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
| @@ -240,7 +268,7 @@ jobs: | |||||||
|   build-docker-image: |   build-docker-image: | ||||||
|     if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-')) |     if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/ng-')) | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     needs: [frontend, tests] |     needs: [frontend, tests, codestyle] | ||||||
|     steps: |     steps: | ||||||
|       - |       - | ||||||
|         name: Prepare |         name: Prepare | ||||||
|   | |||||||
| @@ -77,9 +77,9 @@ The documentation for Paperless-ng is available on [ReadTheDocs](https://paperle | |||||||
|  |  | ||||||
| # Translation | # Translation | ||||||
|  |  | ||||||
| Paperless is currently available in English, German, Dutch and French. Translation is coordinated at transifex: https://www.transifex.com/paperless/paperless-ng | Paperless is currently available in English, German, Dutch, French, and Portuguese. | ||||||
|  |  | ||||||
| If you want to see paperless in your own language, request that language at transifex and you can start translating after I approve the language. | There's an active translation project at transifex! If you want to help out by translating paperless into your language, please head over to https://github.com/jonaswinkler/paperless-ng/issues/212 for details. | ||||||
|  |  | ||||||
| # Feature Requests | # Feature Requests | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,6 +5,19 @@ | |||||||
| Changelog | Changelog | ||||||
| ********* | ********* | ||||||
|  |  | ||||||
|  | paperless-ng 1.2.1 | ||||||
|  | ################## | ||||||
|  |  | ||||||
|  | * `Rodrigo Avelino <https://github.com/rodavelino>`_ translated Paperless into Portuguese (Brazil)! | ||||||
|  |  | ||||||
|  | * The date input fields now respect the currently selected date format. | ||||||
|  |  | ||||||
|  | * Added a fancy icon when adding paperless to the home screen on iOS devices. Thanks to `Joel Nordell <https://github.com/joelnordell>`_. | ||||||
|  |  | ||||||
|  | * When using regular expression matching, the regular expression is now validated before saving the tag/correspondent/type. | ||||||
|  |  | ||||||
|  | * Regression fix: Dates on the front end did not respect date locale settings in some cases. | ||||||
|  |  | ||||||
| paperless-ng 1.2.0 | paperless-ng 1.2.0 | ||||||
| ################## | ################## | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,7 +19,8 @@ | |||||||
| 					"de": "src/locale/messages.de.xlf", | 					"de": "src/locale/messages.de.xlf", | ||||||
| 					"nl-NL": "src/locale/messages.nl_NL.xlf", | 					"nl-NL": "src/locale/messages.nl_NL.xlf", | ||||||
| 					"fr": "src/locale/messages.fr.xlf", | 					"fr": "src/locale/messages.fr.xlf", | ||||||
| 					"en-GB": "src/locale/messages.en_GB.xlf" | 					"en-GB": "src/locale/messages.en_GB.xlf", | ||||||
|  | 					"pt-BR": "src/locale/messages.pt_BR.xlf" | ||||||
| 				} | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"architect": { | 			"architect": { | ||||||
| @@ -36,6 +37,7 @@ | |||||||
| 						"aot": true, | 						"aot": true, | ||||||
| 						"assets": [ | 						"assets": [ | ||||||
| 							"src/favicon.ico", | 							"src/favicon.ico", | ||||||
|  | 							"src/apple-touch-icon.png", | ||||||
| 							"src/assets", | 							"src/assets", | ||||||
| 							"src/manifest.webmanifest", { | 							"src/manifest.webmanifest", { | ||||||
| 								"glob": "pdf.worker.min.js", | 								"glob": "pdf.worker.min.js", | ||||||
| @@ -112,6 +114,7 @@ | |||||||
| 						"karmaConfig": "karma.conf.js", | 						"karmaConfig": "karma.conf.js", | ||||||
| 						"assets": [ | 						"assets": [ | ||||||
| 							"src/favicon.ico", | 							"src/favicon.ico", | ||||||
|  | 							"src/apple-touch-icon.png", | ||||||
| 							"src/assets", | 							"src/assets", | ||||||
| 							"src/manifest.webmanifest" | 							"src/manifest.webmanifest" | ||||||
| 						], | 						], | ||||||
|   | |||||||
| @@ -531,28 +531,21 @@ | |||||||
|         <source>Use system language</source> |         <source>Use system language</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">91</context> |           <context context-type="linenumber">92</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="7729897675462249787" datatype="html"> |       <trans-unit id="7729897675462249787" datatype="html"> | ||||||
|         <source>Use date format of display language</source> |         <source>Use date format of display language</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">96</context> |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |  | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit id="4912706592792948707" datatype="html"> |  | ||||||
|         <source>ISO 8601</source> |  | ||||||
|         <context-group purpose="location"> |  | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |  | ||||||
|           <context context-type="linenumber">97</context> |  | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="8488620293789898901" datatype="html"> |       <trans-unit id="8488620293789898901" datatype="html"> | ||||||
|         <source>Error while storing settings on server: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source> |         <source>Error while storing settings on server: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">114</context> |           <context context-type="linenumber">115</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html"> |       <trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html"> | ||||||
| @@ -1605,6 +1598,13 @@ | |||||||
|           <context context-type="linenumber">21</context> |           <context context-type="linenumber">21</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|  |       <trans-unit id="d6529debfc1613db22d6fa096ebfeb8a85fa739d" datatype="html"> | ||||||
|  |         <source>Invalid date.</source> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> | ||||||
|  |           <context context-type="linenumber">13</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|       <trans-unit id="2807800733729323332" datatype="html"> |       <trans-unit id="2807800733729323332" datatype="html"> | ||||||
|         <source>Yes</source> |         <source>Yes</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
| @@ -1630,35 +1630,49 @@ | |||||||
|         <source>English (US)</source> |         <source>English (US)</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">82</context> |           <context context-type="linenumber">88</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="6987083569809053351" datatype="html"> |       <trans-unit id="6987083569809053351" datatype="html"> | ||||||
|         <source>English (GB)</source> |         <source>English (GB)</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">83</context> |           <context context-type="linenumber">89</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="1858110241312746425" datatype="html"> |       <trans-unit id="1858110241312746425" datatype="html"> | ||||||
|         <source>German</source> |         <source>German</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">84</context> |           <context context-type="linenumber">90</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="3071065188816255493" datatype="html"> |       <trans-unit id="3071065188816255493" datatype="html"> | ||||||
|         <source>Dutch</source> |         <source>Dutch</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">85</context> |           <context context-type="linenumber">91</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="7633754075223722162" datatype="html"> |       <trans-unit id="7633754075223722162" datatype="html"> | ||||||
|         <source>French</source> |         <source>French</source> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">86</context> |           <context context-type="linenumber">92</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit id="9184513005098760425" datatype="html"> | ||||||
|  |         <source>Portuguese (Brazil)</source> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">93</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit id="4912706592792948707" datatype="html"> | ||||||
|  |         <source>ISO 8601</source> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="2119857572761283468" datatype="html"> |       <trans-unit id="2119857572761283468" datatype="html"> | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								src-ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								src-ui/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -2055,9 +2055,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "@ng-bootstrap/ng-bootstrap": { |     "@ng-bootstrap/ng-bootstrap": { | ||||||
|       "version": "8.0.0", |       "version": "8.0.4", | ||||||
|       "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-8.0.0.tgz", |       "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-8.0.4.tgz", | ||||||
|       "integrity": "sha512-v77Gfd8xHH+exq0WqIqVRlxbUEHdA/2+RUJenUP2IDTQN9E1rWl7O461/kosr+0XPuxPArHQJxhh/WsCYckcNg==", |       "integrity": "sha512-EdxTwOPOtlvfnwrglPniulmzdnXdXH3lTGaGAY1HrYRvdtGg6wicRvl+BvwVE/3Qik5NPkOWMVghUHpv3evIYg==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "tslib": "^2.0.0" |         "tslib": "^2.0.0" | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|     "@angular/platform-browser": "~10.1.5", |     "@angular/platform-browser": "~10.1.5", | ||||||
|     "@angular/platform-browser-dynamic": "~10.1.5", |     "@angular/platform-browser-dynamic": "~10.1.5", | ||||||
|     "@angular/router": "~10.1.5", |     "@angular/router": "~10.1.5", | ||||||
|     "@ng-bootstrap/ng-bootstrap": "^8.0.0", |     "@ng-bootstrap/ng-bootstrap": "^8.0.4", | ||||||
|     "@ng-select/ng-select": "^5.0.9", |     "@ng-select/ng-select": "^5.0.9", | ||||||
|     "bootstrap": "^4.5.0", |     "bootstrap": "^4.5.0", | ||||||
|     "file-saver": "^2.0.5", |     "file-saver": "^2.0.5", | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { NgModule } from '@angular/core'; | |||||||
|  |  | ||||||
| import { AppRoutingModule } from './app-routing.module'; | import { AppRoutingModule } from './app-routing.module'; | ||||||
| import { AppComponent } from './app.component'; | import { AppComponent } from './app.component'; | ||||||
| import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; | import { NgbDateAdapter, NgbDateParserFormatter, NgbModule } from '@ng-bootstrap/ng-bootstrap'; | ||||||
| import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; | ||||||
| import { DocumentListComponent } from './components/document-list/document-list.component'; | import { DocumentListComponent } from './components/document-list/document-list.component'; | ||||||
| import { DocumentDetailComponent } from './components/document-detail/document-detail.component'; | import { DocumentDetailComponent } from './components/document-detail/document-detail.component'; | ||||||
| @@ -39,7 +39,6 @@ import { SelectComponent } from './components/common/input/select/select.compone | |||||||
| import { CheckComponent } from './components/common/input/check/check.component'; | import { CheckComponent } from './components/common/input/check/check.component'; | ||||||
| import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component'; | import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component'; | ||||||
| import { InfiniteScrollModule } from 'ngx-infinite-scroll'; | import { InfiniteScrollModule } from 'ngx-infinite-scroll'; | ||||||
| import { DateTimeComponent } from './components/common/input/date-time/date-time.component'; |  | ||||||
| import { TagsComponent } from './components/common/input/tags/tags.component'; | import { TagsComponent } from './components/common/input/tags/tags.component'; | ||||||
| import { SortableDirective } from './directives/sortable.directive'; | import { SortableDirective } from './directives/sortable.directive'; | ||||||
| import { CookieService } from 'ngx-cookie-service'; | import { CookieService } from 'ngx-cookie-service'; | ||||||
| @@ -60,15 +59,21 @@ import { NgSelectModule } from '@ng-select/ng-select'; | |||||||
| import { NumberComponent } from './components/common/input/number/number.component'; | import { NumberComponent } from './components/common/input/number/number.component'; | ||||||
| import { SafePipe } from './pipes/safe.pipe'; | import { SafePipe } from './pipes/safe.pipe'; | ||||||
| import { CustomDatePipe } from './pipes/custom-date.pipe'; | import { CustomDatePipe } from './pipes/custom-date.pipe'; | ||||||
|  | import { DateComponent } from './components/common/input/date/date.component'; | ||||||
|  | import { ISODateTimeAdapter } from './utils/ngb-iso-date-time-adapter'; | ||||||
|  | import { LocalizedDateParserFormatter } from './utils/ngb-date-parser-formatter'; | ||||||
|  | import { ApiVersionInterceptor } from './interceptors/api-version.interceptor'; | ||||||
|  |  | ||||||
| import localeFr from '@angular/common/locales/fr'; | import localeFr from '@angular/common/locales/fr'; | ||||||
| import localeNl from '@angular/common/locales/nl'; | import localeNl from '@angular/common/locales/nl'; | ||||||
| import localeDe from '@angular/common/locales/de'; | import localeDe from '@angular/common/locales/de'; | ||||||
|  | import localePt from '@angular/common/locales/pt'; | ||||||
| import localeEnGb from '@angular/common/locales/en-GB'; | import localeEnGb from '@angular/common/locales/en-GB'; | ||||||
|  |  | ||||||
| registerLocaleData(localeFr) | registerLocaleData(localeFr) | ||||||
| registerLocaleData(localeNl) | registerLocaleData(localeNl) | ||||||
| registerLocaleData(localeDe) | registerLocaleData(localeDe) | ||||||
|  | registerLocaleData(localePt, "pt-BR") | ||||||
| registerLocaleData(localeEnGb) | registerLocaleData(localeEnGb) | ||||||
|  |  | ||||||
| @NgModule({ | @NgModule({ | ||||||
| @@ -104,7 +109,6 @@ registerLocaleData(localeEnGb) | |||||||
|     SelectComponent, |     SelectComponent, | ||||||
|     CheckComponent, |     CheckComponent, | ||||||
|     SaveViewConfigDialogComponent, |     SaveViewConfigDialogComponent, | ||||||
|     DateTimeComponent, |  | ||||||
|     TagsComponent, |     TagsComponent, | ||||||
|     SortableDirective, |     SortableDirective, | ||||||
|     SavedViewWidgetComponent, |     SavedViewWidgetComponent, | ||||||
| @@ -120,7 +124,8 @@ registerLocaleData(localeEnGb) | |||||||
|     SelectDialogComponent, |     SelectDialogComponent, | ||||||
|     NumberComponent, |     NumberComponent, | ||||||
|     SafePipe, |     SafePipe, | ||||||
|     CustomDatePipe |     CustomDatePipe, | ||||||
|  |     DateComponent | ||||||
|   ], |   ], | ||||||
|   imports: [ |   imports: [ | ||||||
|     BrowserModule, |     BrowserModule, | ||||||
| @@ -140,9 +145,15 @@ registerLocaleData(localeEnGb) | |||||||
|       provide: HTTP_INTERCEPTORS, |       provide: HTTP_INTERCEPTORS, | ||||||
|       useClass: CsrfInterceptor, |       useClass: CsrfInterceptor, | ||||||
|       multi: true |       multi: true | ||||||
|  |     },{ | ||||||
|  |       provide: HTTP_INTERCEPTORS, | ||||||
|  |       useClass: ApiVersionInterceptor, | ||||||
|  |       multi: true | ||||||
|     }, |     }, | ||||||
|     FilterPipe, |     FilterPipe, | ||||||
|     DocumentTitlePipe |     DocumentTitlePipe, | ||||||
|  |     {provide: NgbDateAdapter, useClass: ISODateTimeAdapter}, | ||||||
|  |     {provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter} | ||||||
|   ], |   ], | ||||||
|   bootstrap: [AppComponent] |   bootstrap: [AppComponent] | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ | |||||||
|               </svg> {{d.title | documentTitle}} |               </svg> {{d.title | documentTitle}} | ||||||
|             </a> |             </a> | ||||||
|           </li> |           </li> | ||||||
|           <li class="nav-item w-100" *ngIf="openDocuments.length > 1"> |           <li class="nav-item w-100" *ngIf="openDocuments.length >= 1"> | ||||||
|             <a class="nav-link text-truncate" [routerLink]="" (click)="closeAll()"> |             <a class="nav-link text-truncate" [routerLink]="" (click)="closeAll()"> | ||||||
|               <svg class="sidebaricon" fill="currentColor"> |               <svg class="sidebaricon" fill="currentColor"> | ||||||
|                 <use xlink:href="assets/bootstrap-icons.svg#x"/> |                 <use xlink:href="assets/bootstrap-icons.svg#x"/> | ||||||
|   | |||||||
| @@ -20,9 +20,18 @@ | |||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|           <div class="input-group input-group-sm"> |           <div class="input-group input-group-sm"> | ||||||
|             <input type="date" class="form-control" id="date_after" [(ngModel)]="dateAfter" (change)="onChangeDebounce()"> |             <input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" | ||||||
|  |                     [(ngModel)]="dateAfter" ngbDatepicker #dateAfterPicker="ngbDatepicker"> | ||||||
|  |             <div class="input-group-append"> | ||||||
|  |               <button class="btn btn-outline-secondary" (click)="dateAfterPicker.toggle()" type="button"> | ||||||
|  |                 <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16"> | ||||||
|  |                   <path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/> | ||||||
|  |                 </svg> | ||||||
|  |               </button> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|  |         </div> | ||||||
|         <div class="list-group-item d-flex flex-column align-items-start" role="menuitem"> |         <div class="list-group-item d-flex flex-column align-items-start" role="menuitem"> | ||||||
|  |  | ||||||
|           <div class="mb-2 d-flex flex-row w-100 justify-content-between small"> |           <div class="mb-2 d-flex flex-row w-100 justify-content-between small"> | ||||||
| @@ -36,8 +45,17 @@ | |||||||
|           </div> |           </div> | ||||||
|  |  | ||||||
|           <div class="input-group input-group-sm"> |           <div class="input-group input-group-sm"> | ||||||
|             <input type="date" class="form-control" id="date_before" [(ngModel)]="dateBefore" (change)="onChangeDebounce()"> |             <input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" | ||||||
|           </div> |                     [(ngModel)]="dateBefore" ngbDatepicker #dateBeforePicker="ngbDatepicker"> | ||||||
|  |             <div class="input-group-append"> | ||||||
|  |               <button class="btn btn-outline-secondary" (click)="dateBeforePicker.toggle()" type="button"> | ||||||
|  |                 <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16"> | ||||||
|  |                   <path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/> | ||||||
|  |                 </svg> | ||||||
|  |               </button> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |            | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -1,7 +1,10 @@ | |||||||
| import { formatDate } from '@angular/common'; | import { formatDate } from '@angular/common'; | ||||||
| import { Component, EventEmitter, Input, Output, OnInit, OnDestroy } from '@angular/core'; | import { Component, EventEmitter, Input, Output, OnInit, OnDestroy } from '@angular/core'; | ||||||
|  | import { NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; | ||||||
| import { Subject, Subscription } from 'rxjs'; | import { Subject, Subscription } from 'rxjs'; | ||||||
| import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; | import { debounceTime } from 'rxjs/operators'; | ||||||
|  | import { SettingsService } from 'src/app/services/settings.service'; | ||||||
|  | import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter'; | ||||||
|  |  | ||||||
| export interface DateSelection { | export interface DateSelection { | ||||||
|   before?: string |   before?: string | ||||||
| @@ -16,10 +19,17 @@ const LAST_YEAR = 3 | |||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-date-dropdown', |   selector: 'app-date-dropdown', | ||||||
|   templateUrl: './date-dropdown.component.html', |   templateUrl: './date-dropdown.component.html', | ||||||
|   styleUrls: ['./date-dropdown.component.scss'] |   styleUrls: ['./date-dropdown.component.scss'], | ||||||
|  |   providers: [ | ||||||
|  |     {provide: NgbDateAdapter, useClass: ISODateAdapter}, | ||||||
|  |   ] | ||||||
| }) | }) | ||||||
| export class DateDropdownComponent implements OnInit, OnDestroy { | export class DateDropdownComponent implements OnInit, OnDestroy { | ||||||
|  |  | ||||||
|  |   constructor(settings: SettingsService) { | ||||||
|  |     this.datePlaceHolder = settings.getLocalizedDateInputFormat() | ||||||
|  |   } | ||||||
|  |  | ||||||
|   quickFilters = [ |   quickFilters = [ | ||||||
|     {id: LAST_7_DAYS, name: $localize`Last 7 days`}, |     {id: LAST_7_DAYS, name: $localize`Last 7 days`}, | ||||||
|     {id: LAST_MONTH, name: $localize`Last month`}, |     {id: LAST_MONTH, name: $localize`Last month`}, | ||||||
| @@ -27,6 +37,8 @@ export class DateDropdownComponent implements OnInit, OnDestroy { | |||||||
|     {id: LAST_YEAR, name: $localize`Last year`} |     {id: LAST_YEAR, name: $localize`Last year`} | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
|  |   datePlaceHolder: string | ||||||
|  |  | ||||||
|   @Input() |   @Input() | ||||||
|   dateBefore: string |   dateBefore: string | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,13 +0,0 @@ | |||||||
| <div class="form-row"> |  | ||||||
|   <div class="form-group col"> |  | ||||||
|       <label for="created_date">{{titleDate}}</label> |  | ||||||
|       <input type="date" class="form-control" id="created_date" [(ngModel)]="dateValue" (change)="dateOrTimeChanged()"> |  | ||||||
|   </div> |  | ||||||
|   <div class="form-group col" *ngIf="titleTime"> |  | ||||||
|       <label for="created_time">{{titleTime}}</label> |  | ||||||
|       <input type="time" class="form-control" id="created_time" [(ngModel)]="timeValue" (change)="dateOrTimeChanged()"> |  | ||||||
|   </div> |  | ||||||
| </div> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <!-- <small *ngIf="hint" class="form-text text-muted">{{hint}}</small> --> |  | ||||||
| @@ -1,61 +0,0 @@ | |||||||
| import { formatDate } from '@angular/common'; |  | ||||||
| import { Component, forwardRef, Input, OnInit } from '@angular/core'; |  | ||||||
| import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; |  | ||||||
|  |  | ||||||
| @Component({ |  | ||||||
|   providers: [{ |  | ||||||
|     provide: NG_VALUE_ACCESSOR, |  | ||||||
|     useExisting: forwardRef(() => DateTimeComponent), |  | ||||||
|     multi: true |  | ||||||
|   }], |  | ||||||
|   selector: 'app-input-date-time', |  | ||||||
|   templateUrl: './date-time.component.html', |  | ||||||
|   styleUrls: ['./date-time.component.scss'] |  | ||||||
| }) |  | ||||||
| export class DateTimeComponent implements OnInit,ControlValueAccessor  { |  | ||||||
|  |  | ||||||
|   constructor() { |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   onChange = (newValue: any) => {}; |  | ||||||
|    |  | ||||||
|   onTouched = () => {}; |  | ||||||
|  |  | ||||||
|   writeValue(newValue: any): void { |  | ||||||
|     this.dateValue = formatDate(newValue, 'yyyy-MM-dd', "en-US") |  | ||||||
|     this.timeValue = formatDate(newValue, 'HH:mm:ss', 'en-US') |  | ||||||
|   } |  | ||||||
|   registerOnChange(fn: any): void { |  | ||||||
|     this.onChange = fn; |  | ||||||
|   } |  | ||||||
|   registerOnTouched(fn: any): void { |  | ||||||
|     this.onTouched = fn; |  | ||||||
|   } |  | ||||||
|   setDisabledState?(isDisabled: boolean): void { |  | ||||||
|     this.disabled = isDisabled; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @Input() |  | ||||||
|   titleDate: string = "Date" |  | ||||||
|  |  | ||||||
|   @Input() |  | ||||||
|   titleTime: string |  | ||||||
|  |  | ||||||
|   @Input() |  | ||||||
|   disabled: boolean = false |  | ||||||
|  |  | ||||||
|   @Input() |  | ||||||
|   hint: string |  | ||||||
|  |  | ||||||
|   timeValue |  | ||||||
|  |  | ||||||
|   dateValue |  | ||||||
|  |  | ||||||
|   ngOnInit(): void { |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   dateOrTimeChanged() { |  | ||||||
|     this.onChange(formatDate(this.dateValue + "T" + this.timeValue,"yyyy-MM-ddTHH:mm:ssZZZZZ", "en-us", "UTC")) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -0,0 +1,16 @@ | |||||||
|  | <div class="form-group"> | ||||||
|  |   <label [for]="inputId">{{title}}</label> | ||||||
|  |   <div class="input-group" [class.is-invalid]="error"> | ||||||
|  |     <input class="form-control" [class.is-invalid]="error"  [placeholder]="placeholder" [id]="inputId" (dateSelect)="onChange(value)" (change)="onChange(value)" | ||||||
|  |            name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel"> | ||||||
|  |     <div class="input-group-append"> | ||||||
|  |       <button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button"> | ||||||
|  |         <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16"> | ||||||
|  |           <path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/> | ||||||
|  |         </svg> | ||||||
|  |       </button> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  |   <div class="invalid-feedback" i18n>Invalid date.</div> | ||||||
|  |   <small *ngIf="hint" class="form-text text-muted">{{hint}}</small> | ||||||
|  | </div> | ||||||
| @@ -1,20 +1,20 @@ | |||||||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||||
| 
 | 
 | ||||||
| import { DateTimeComponent } from './date-time.component'; | import { DateComponent } from './date.component'; | ||||||
| 
 | 
 | ||||||
| describe('DateTimeComponent', () => { | describe('DateComponent', () => { | ||||||
|   let component: DateTimeComponent; |   let component: DateComponent; | ||||||
|   let fixture: ComponentFixture<DateTimeComponent>; |   let fixture: ComponentFixture<DateComponent>; | ||||||
| 
 | 
 | ||||||
|   beforeEach(async () => { |   beforeEach(async () => { | ||||||
|     await TestBed.configureTestingModule({ |     await TestBed.configureTestingModule({ | ||||||
|       declarations: [ DateTimeComponent ] |       declarations: [ DateComponent ] | ||||||
|     }) |     }) | ||||||
|     .compileComponents(); |     .compileComponents(); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   beforeEach(() => { |   beforeEach(() => { | ||||||
|     fixture = TestBed.createComponent(DateTimeComponent); |     fixture = TestBed.createComponent(DateComponent); | ||||||
|     component = fixture.componentInstance; |     component = fixture.componentInstance; | ||||||
|     fixture.detectChanges(); |     fixture.detectChanges(); | ||||||
|   }); |   }); | ||||||
| @@ -0,0 +1,32 @@ | |||||||
|  | import { Component, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; | ||||||
|  | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; | ||||||
|  | import { NgbDateAdapter, NgbDateParserFormatter, NgbDatepickerContent } from '@ng-bootstrap/ng-bootstrap'; | ||||||
|  | import { SettingsService } from 'src/app/services/settings.service'; | ||||||
|  | import { v4 as uuidv4 } from 'uuid'; | ||||||
|  | import { AbstractInputComponent } from '../abstract-input'; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @Component({ | ||||||
|  |   providers: [{ | ||||||
|  |     provide: NG_VALUE_ACCESSOR, | ||||||
|  |     useExisting: forwardRef(() => DateComponent), | ||||||
|  |     multi: true | ||||||
|  |   }], | ||||||
|  |   selector: 'app-input-date', | ||||||
|  |   templateUrl: './date.component.html', | ||||||
|  |   styleUrls: ['./date.component.scss'] | ||||||
|  | }) | ||||||
|  | export class DateComponent extends AbstractInputComponent<string> implements OnInit { | ||||||
|  |  | ||||||
|  |   constructor(private settings: SettingsService) { | ||||||
|  |     super() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ngOnInit(): void { | ||||||
|  |     super.ngOnInit() | ||||||
|  |     this.placeholder = this.settings.getLocalizedDateInputFormat() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   placeholder: string | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -58,7 +58,7 @@ | |||||||
|  |  | ||||||
|                         <app-input-text #inputTitle i18n-title title="Title" formControlName="title" [error]="error?.title"></app-input-text> |                         <app-input-text #inputTitle i18n-title title="Title" formControlName="title" [error]="error?.title"></app-input-text> | ||||||
|                         <app-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" formControlName='archive_serial_number'></app-input-number> |                         <app-input-number i18n-title title="Archive serial number" [error]="error?.archive_serial_number" formControlName='archive_serial_number'></app-input-number> | ||||||
|                         <app-input-date-time i18n-titleDate titleDate="Date created" formControlName="created"></app-input-date-time> |                         <app-input-date i18n-title title="Date created" formControlName="created" [error]="error?.created"></app-input-date> | ||||||
|                         <app-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" |                         <app-input-select [items]="correspondents" i18n-title title="Correspondent" formControlName="correspondent" [allowNull]="true" | ||||||
|                             (createNew)="createCorrespondent()" [suggestions]="suggestions?.correspondents"></app-input-select> |                             (createNew)="createCorrespondent()" [suggestions]="suggestions?.correspondents"></app-input-select> | ||||||
|                         <app-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" |                         <app-input-select [items]="documentTypes" i18n-title title="Document type" formControlName="document_type" [allowNull]="true" | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|   <div class="modal-body"> |   <div class="modal-body"> | ||||||
|     <app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text> |     <app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text> | ||||||
|     <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> |     <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||||
|     <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match"></app-input-text> |     <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></app-input-text> | ||||||
|     <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></app-input-check> |     <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive" novalidate></app-input-check> | ||||||
|   </div> |   </div> | ||||||
|   <div class="modal-footer"> |   <div class="modal-footer"> | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
|  |  | ||||||
|       <app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text> |       <app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text> | ||||||
|       <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> |       <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||||
|       <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match"></app-input-text> |       <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></app-input-text> | ||||||
|       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> |       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||||
|  |  | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -88,14 +88,15 @@ export class SettingsComponent implements OnInit { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   get displayLanguageOptions(): LanguageOption[] { |   get displayLanguageOptions(): LanguageOption[] { | ||||||
|     return [{code: "", name: $localize`Use system language`}].concat(this.settings.getLanguageOptions()) |     return [ | ||||||
|  |       {code: "", name: $localize`Use system language`} | ||||||
|  |     ].concat(this.settings.getLanguageOptions()) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   get dateLocaleOptions(): LanguageOption[] { |   get dateLocaleOptions(): LanguageOption[] { | ||||||
|     return [ |     return [ | ||||||
|       {code: "", name: $localize`Use date format of display language`}, |       {code: "", name: $localize`Use date format of display language`} | ||||||
|       {code: "iso-8601", name: $localize`ISO 8601`} |     ].concat(this.settings.getDateLocaleOptions()) | ||||||
|     ].concat(this.settings.getLanguageOptions()) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   get today() { |   get today() { | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|  |  | ||||||
|       <app-input-check i18n-title title="Inbox tag" formControlName="is_inbox_tag" i18n-hint hint="Inbox tags are automatically assigned to all consumed documents."></app-input-check> |       <app-input-check i18n-title title="Inbox tag" formControlName="is_inbox_tag" i18n-hint hint="Inbox tags are automatically assigned to all consumed documents."></app-input-check> | ||||||
|       <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> |       <app-input-select i18n-title title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||||
|       <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match"></app-input-text> |       <app-input-text *ngIf="patternRequired" i18n-title title="Matching pattern" formControlName="match" [error]="error?.match"></app-input-text> | ||||||
|       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> |       <app-input-check *ngIf="patternRequired" i18n-title title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||||
|     </div> |     </div> | ||||||
|     <div class="modal-footer"> |     <div class="modal-footer"> | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								src-ui/src/app/interceptors/api-version.interceptor.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src-ui/src/app/interceptors/api-version.interceptor.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | import { TestBed } from '@angular/core/testing'; | ||||||
|  |  | ||||||
|  | import { ApiVersionInterceptor } from './api-version.interceptor'; | ||||||
|  |  | ||||||
|  | describe('ApiVersionInterceptor', () => { | ||||||
|  |   beforeEach(() => TestBed.configureTestingModule({ | ||||||
|  |     providers: [ | ||||||
|  |       ApiVersionInterceptor | ||||||
|  |       ] | ||||||
|  |   })); | ||||||
|  |  | ||||||
|  |   it('should be created', () => { | ||||||
|  |     const interceptor: ApiVersionInterceptor = TestBed.inject(ApiVersionInterceptor); | ||||||
|  |     expect(interceptor).toBeTruthy(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
							
								
								
									
										25
									
								
								src-ui/src/app/interceptors/api-version.interceptor.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src-ui/src/app/interceptors/api-version.interceptor.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | import { Injectable } from '@angular/core'; | ||||||
|  | import { | ||||||
|  |   HttpRequest, | ||||||
|  |   HttpHandler, | ||||||
|  |   HttpEvent, | ||||||
|  |   HttpInterceptor | ||||||
|  | } from '@angular/common/http'; | ||||||
|  | import { Observable } from 'rxjs'; | ||||||
|  | import { environment } from 'src/environments/environment'; | ||||||
|  |  | ||||||
|  | @Injectable() | ||||||
|  | export class ApiVersionInterceptor implements HttpInterceptor { | ||||||
|  |  | ||||||
|  |   constructor() {} | ||||||
|  |  | ||||||
|  |   intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { | ||||||
|  |     request = request.clone({ | ||||||
|  |         setHeaders: { | ||||||
|  |           'Accept': `application/json; version=${environment.apiVersion}` | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |   | ||||||
|  |     return next.handle(request); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -13,17 +13,20 @@ const FORMAT_TO_ISO_FORMAT = { | |||||||
| }) | }) | ||||||
| export class CustomDatePipe extends DatePipe implements PipeTransform { | export class CustomDatePipe extends DatePipe implements PipeTransform { | ||||||
|  |  | ||||||
|  |   private defaultLocale: string | ||||||
|  |  | ||||||
|   constructor(@Inject(LOCALE_ID) locale: string, private settings: SettingsService) { |   constructor(@Inject(LOCALE_ID) locale: string, private settings: SettingsService) { | ||||||
|     super(locale) |     super(locale) | ||||||
|  |     this.defaultLocale = locale | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   transform(value: any, format?: string, timezone?: string, locale?: string): string | null { |   transform(value: any, format?: string, timezone?: string, locale?: string): string | null { | ||||||
|     let l = locale || this.settings.get(SETTINGS_KEYS.DATE_LOCALE) |     let l = locale || this.settings.get(SETTINGS_KEYS.DATE_LOCALE) || this.defaultLocale | ||||||
|     let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT) |     let f = format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT) | ||||||
|     if (l == "iso-8601") { |     if (l == "iso-8601") { | ||||||
|       return super.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone) |       return super.transform(value, FORMAT_TO_ISO_FORMAT[f], timezone) | ||||||
|     } else { |     } else { | ||||||
|       return super.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, locale) |       return super.transform(value, format || this.settings.get(SETTINGS_KEYS.DATE_FORMAT), timezone, l) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { DOCUMENT } from '@angular/common'; | import { DOCUMENT } from '@angular/common'; | ||||||
| import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; | import { Inject, Injectable, LOCALE_ID, Renderer2, RendererFactory2 } from '@angular/core'; | ||||||
| import { Meta } from '@angular/platform-browser'; | import { Meta } from '@angular/platform-browser'; | ||||||
| import { CookieService } from 'ngx-cookie-service'; | import { CookieService } from 'ngx-cookie-service'; | ||||||
|  |  | ||||||
| @@ -10,9 +10,14 @@ export interface PaperlessSettings { | |||||||
| } | } | ||||||
|  |  | ||||||
| export interface LanguageOption { | export interface LanguageOption { | ||||||
|   code: string, |   code: string | ||||||
|   name: string, |   name: string | ||||||
|   englishName?: string |   englishName?: string | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * A date format string for use by the date selectors. MUST contain 'yyyy', 'mm' and 'dd'. | ||||||
|  |    */ | ||||||
|  |   dateInputFormat?: string | ||||||
| } | } | ||||||
|  |  | ||||||
| export const SETTINGS_KEYS = { | export const SETTINGS_KEYS = { | ||||||
| @@ -56,7 +61,8 @@ export class SettingsService { | |||||||
|     private rendererFactory: RendererFactory2, |     private rendererFactory: RendererFactory2, | ||||||
|     @Inject(DOCUMENT) private document, |     @Inject(DOCUMENT) private document, | ||||||
|     private cookieService: CookieService, |     private cookieService: CookieService, | ||||||
|     private meta: Meta |     private meta: Meta, | ||||||
|  |     @Inject(LOCALE_ID) private localeId: string | ||||||
|   ) { |   ) { | ||||||
|     this.renderer = rendererFactory.createRenderer(null, null); |     this.renderer = rendererFactory.createRenderer(null, null); | ||||||
|  |  | ||||||
| @@ -79,14 +85,20 @@ export class SettingsService { | |||||||
|  |  | ||||||
|   getLanguageOptions(): LanguageOption[] { |   getLanguageOptions(): LanguageOption[] { | ||||||
|     return [ |     return [ | ||||||
|       {code: "en-us", name: $localize`English (US)`, englishName: "English (US)"}, |       {code: "en-us", name: $localize`English (US)`, englishName: "English (US)", dateInputFormat: "mm/dd/yyyy"}, | ||||||
|       {code: "en-gb", name: $localize`English (GB)`, englishName: "English (GB)"}, |       {code: "en-gb", name: $localize`English (GB)`, englishName: "English (GB)", dateInputFormat: "dd/mm/yyyy"}, | ||||||
|       {code: "de", name: $localize`German`, englishName: "German"}, |       {code: "de", name: $localize`German`, englishName: "German", dateInputFormat: "dd.mm.yyyy"}, | ||||||
|       {code: "nl", name: $localize`Dutch`, englishName: "Dutch"}, |       {code: "nl", name: $localize`Dutch`, englishName: "Dutch", dateInputFormat: "dd-mm-yyyy"}, | ||||||
|       {code: "fr", name: $localize`French`, englishName: "French"} |       {code: "fr", name: $localize`French`, englishName: "French", dateInputFormat: "dd/mm/yyyy"}, | ||||||
|  |       {code: "pt-br", name: $localize`Portuguese (Brazil)`, englishName: "Portuguese (Brazil)", dateInputFormat: "dd/mm/yyyy"} | ||||||
|     ] |     ] | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getDateLocaleOptions(): LanguageOption[] { | ||||||
|  |     let isoOption: LanguageOption = {code: "iso-8601", name: $localize`ISO 8601`, dateInputFormat: "yyyy-mm-dd"} | ||||||
|  |     return [isoOption].concat(this.getLanguageOptions()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   private getLanguageCookieName() { |   private getLanguageCookieName() { | ||||||
|     let prefix = "" |     let prefix = "" | ||||||
|     if (this.meta.getTag('name=cookie_prefix')) { |     if (this.meta.getTag('name=cookie_prefix')) { | ||||||
| @@ -107,6 +119,11 @@ export class SettingsService { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getLocalizedDateInputFormat(): string { | ||||||
|  |     let dateLocale = this.get(SETTINGS_KEYS.DATE_LOCALE) || this.getLanguage() || this.localeId.toLowerCase() | ||||||
|  |     return this.getDateLocaleOptions().find(o => o.code == dateLocale)?.dateInputFormat || "yyyy-mm-dd" | ||||||
|  |   } | ||||||
|  |  | ||||||
|   get(key: string): any { |   get(key: string): any { | ||||||
|     let setting = SETTINGS.find(s => s.key == key) |     let setting = SETTINGS.find(s => s.key == key) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										59
									
								
								src-ui/src/app/utils/ngb-date-parser-formatter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src-ui/src/app/utils/ngb-date-parser-formatter.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | import { Injectable } from "@angular/core" | ||||||
|  | import { NgbDateParserFormatter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap" | ||||||
|  | import { SettingsService } from "../services/settings.service" | ||||||
|  |  | ||||||
|  | @Injectable() | ||||||
|  | export class LocalizedDateParserFormatter extends NgbDateParserFormatter { | ||||||
|  |  | ||||||
|  |   constructor(private settings: SettingsService) { | ||||||
|  |     super() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private getDateInputFormat() { | ||||||
|  |     return this.settings.getLocalizedDateInputFormat() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * This constructs a regular expression from a date input format which is then | ||||||
|  |    * used to parse dates. | ||||||
|  |    */ | ||||||
|  |   private getDateParseRegex() { | ||||||
|  |     return new RegExp( | ||||||
|  |       "^" + this.getDateInputFormat() | ||||||
|  |       .replace('dd', '(?<day>[0-9]+)') | ||||||
|  |       .replace('mm', '(?<month>[0-9]+)') | ||||||
|  |       .replace('yyyy', '(?<year>[0-9]+)') | ||||||
|  |       .split('.').join('\\.\\s*') + "$" // allow whitespace(s) after dot (specific for German) | ||||||
|  |       ) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   parse(value: string): NgbDateStruct | null { | ||||||
|  |     let match = this.getDateParseRegex().exec(value) | ||||||
|  |     if (match) { | ||||||
|  |       let dateStruct = { | ||||||
|  |         day: +match.groups.day, | ||||||
|  |         month: +match.groups.month, | ||||||
|  |         year: +match.groups.year | ||||||
|  |       } | ||||||
|  |       if (dateStruct.year <= (new Date().getFullYear() - 2000)) { | ||||||
|  |         dateStruct.year += 2000 | ||||||
|  |       } else if (dateStruct.year < 100) { | ||||||
|  |         dateStruct.year += 1900 | ||||||
|  |       } | ||||||
|  |       return dateStruct | ||||||
|  |     } else { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   format(date: NgbDateStruct | null): string { | ||||||
|  |     if (date) { | ||||||
|  |       return this.getDateInputFormat() | ||||||
|  |       .replace('dd', date.day.toString().padStart(2, '0')) | ||||||
|  |       .replace('mm', date.month.toString().padStart(2, '0')) | ||||||
|  |       .replace('yyyy', date.year.toString().padStart(4, '0')) | ||||||
|  |     } else { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								src-ui/src/app/utils/ngb-iso-date-adapter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src-ui/src/app/utils/ngb-iso-date-adapter.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | import { Injectable } from "@angular/core"; | ||||||
|  | import { NgbDateAdapter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap"; | ||||||
|  |  | ||||||
|  | @Injectable() | ||||||
|  | export class ISODateAdapter extends NgbDateAdapter<string> { | ||||||
|  |  | ||||||
|  |   fromModel(value: string | null): NgbDateStruct | null { | ||||||
|  |     if (value) { | ||||||
|  |       let date = new Date(value) | ||||||
|  |       return { | ||||||
|  |         day : date.getDate(), | ||||||
|  |         month : date.getMonth() + 1, | ||||||
|  |         year : date.getFullYear() | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   toModel(date: NgbDateStruct | null): string | null { | ||||||
|  |     if (date) { | ||||||
|  |       return date.year.toString().padStart(4, '0') + "-" + date.month.toString().padStart(2, '0') + "-" + date.day.toString().padStart(2, '0') | ||||||
|  |     } else { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								src-ui/src/app/utils/ngb-iso-date-time-adapter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src-ui/src/app/utils/ngb-iso-date-time-adapter.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | import { Injectable } from "@angular/core"; | ||||||
|  | import { NgbDateAdapter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap"; | ||||||
|  |  | ||||||
|  | @Injectable() | ||||||
|  | export class ISODateTimeAdapter extends NgbDateAdapter<string> { | ||||||
|  |  | ||||||
|  |   fromModel(value: string | null): NgbDateStruct | null { | ||||||
|  |     if (value) { | ||||||
|  |       let date = new Date(value) | ||||||
|  |       return { | ||||||
|  |         day : date.getDate(), | ||||||
|  |         month : date.getMonth() + 1, | ||||||
|  |         year : date.getFullYear() | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       return null | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   toModel(date: NgbDateStruct | null): string | null { | ||||||
|  |     return date ? new Date(date.year, date.month - 1, date.day).toISOString() : null | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								src-ui/src/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src-ui/src/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.1 KiB | 
| @@ -1,8 +1,9 @@ | |||||||
| export const environment = { | export const environment = { | ||||||
|   production: true, |   production: true, | ||||||
|   apiBaseUrl: "/api/", |   apiBaseUrl: "/api/", | ||||||
|  |   apiVersion: "1", | ||||||
|   appTitle: "Paperless-ng", |   appTitle: "Paperless-ng", | ||||||
|   version: "1.2.0", |   version: "1.2.1", | ||||||
|   webSocketHost: window.location.host, |   webSocketHost: window.location.host, | ||||||
|   webSocketProtocol: (window.location.protocol == "https:" ? "wss:" : "ws:") |   webSocketProtocol: (window.location.protocol == "https:" ? "wss:" : "ws:") | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| export const environment = { | export const environment = { | ||||||
|   production: false, |   production: false, | ||||||
|   apiBaseUrl: "http://localhost:8000/api/", |   apiBaseUrl: "http://localhost:8000/api/", | ||||||
|  |   apiVersion: "1", | ||||||
|   appTitle: "Paperless-ng", |   appTitle: "Paperless-ng", | ||||||
|   version: "DEVELOPMENT", |   version: "DEVELOPMENT", | ||||||
|   webSocketHost: "localhost:8000", |   webSocketHost: "localhost:8000", | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
|   <meta name="theme-color" content="#17541f" /> |   <meta name="theme-color" content="#17541f" /> | ||||||
|   <link rel="manifest" href="manifest.webmanifest"> |   <link rel="manifest" href="manifest.webmanifest"> | ||||||
|   <link rel="icon" type="image/x-icon" href="favicon.ico"> |   <link rel="icon" type="image/x-icon" href="favicon.ico"> | ||||||
|  |   <link rel="apple-touch-icon" href="apple-touch-icon.png"> | ||||||
| </head> | </head> | ||||||
| <body class="color-scheme-system"> | <body class="color-scheme-system"> | ||||||
|   <app-root></app-root> |   <app-root></app-root> | ||||||
|   | |||||||
| @@ -606,7 +606,7 @@ | |||||||
|         <target>Benutze Systemsprache</target> |         <target>Benutze Systemsprache</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">91</context> |           <context context-type="linenumber">92</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7729897675462249787"> |       <trans-unit datatype="html" id="7729897675462249787"> | ||||||
| @@ -614,15 +614,7 @@ | |||||||
|         <target>Benutze Datumsformat der Anzeigesprache</target> |         <target>Benutze Datumsformat der Anzeigesprache</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">96</context> |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |  | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit datatype="html" id="4912706592792948707"> |  | ||||||
|         <source>ISO 8601</source> |  | ||||||
|         <target>ISO 8601</target> |  | ||||||
|         <context-group purpose="location"> |  | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |  | ||||||
|           <context context-type="linenumber">97</context> |  | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="8488620293789898901"> |       <trans-unit datatype="html" id="8488620293789898901"> | ||||||
| @@ -630,7 +622,7 @@ | |||||||
|         <target>Fehler beim Speichern der Einstellungen auf dem Server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> |         <target>Fehler beim Speichern der Einstellungen auf dem Server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">114</context> |           <context context-type="linenumber">115</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> |       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> | ||||||
| @@ -1832,6 +1824,14 @@ | |||||||
|           <context context-type="linenumber">21</context> |           <context context-type="linenumber">21</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="d6529debfc1613db22d6fa096ebfeb8a85fa739d"> | ||||||
|  |         <source>Invalid date.</source> | ||||||
|  |         <target>Ungültiges Datum.</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> | ||||||
|  |           <context context-type="linenumber">13</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2807800733729323332"> |       <trans-unit datatype="html" id="2807800733729323332"> | ||||||
|         <source>Yes</source> |         <source>Yes</source> | ||||||
|         <target>Ja</target> |         <target>Ja</target> | ||||||
| @@ -1861,7 +1861,7 @@ | |||||||
|         <target>Englisch (US)</target> |         <target>Englisch (US)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">82</context> |           <context context-type="linenumber">88</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="6987083569809053351"> |       <trans-unit datatype="html" id="6987083569809053351"> | ||||||
| @@ -1869,7 +1869,7 @@ | |||||||
|         <target>Englisch (UK)</target> |         <target>Englisch (UK)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">83</context> |           <context context-type="linenumber">89</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="1858110241312746425"> |       <trans-unit datatype="html" id="1858110241312746425"> | ||||||
| @@ -1877,7 +1877,7 @@ | |||||||
|         <target>Deutsch</target> |         <target>Deutsch</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">84</context> |           <context context-type="linenumber">90</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="3071065188816255493"> |       <trans-unit datatype="html" id="3071065188816255493"> | ||||||
| @@ -1885,7 +1885,7 @@ | |||||||
|         <target>Niederländisch</target> |         <target>Niederländisch</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">85</context> |           <context context-type="linenumber">91</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7633754075223722162"> |       <trans-unit datatype="html" id="7633754075223722162"> | ||||||
| @@ -1893,7 +1893,23 @@ | |||||||
|         <target>Französisch</target> |         <target>Französisch</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">86</context> |           <context context-type="linenumber">92</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="9184513005098760425"> | ||||||
|  |         <source>Portuguese (Brazil)</source> | ||||||
|  |         <target>Portugiesisch (Brasilien)</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">93</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="4912706592792948707"> | ||||||
|  |         <source>ISO 8601</source> | ||||||
|  |         <target>ISO 8601</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2119857572761283468"> |       <trans-unit datatype="html" id="2119857572761283468"> | ||||||
|   | |||||||
| @@ -606,7 +606,7 @@ | |||||||
|         <target>Use system language</target> |         <target>Use system language</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">91</context> |           <context context-type="linenumber">92</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7729897675462249787"> |       <trans-unit datatype="html" id="7729897675462249787"> | ||||||
| @@ -614,15 +614,7 @@ | |||||||
|         <target>Use date format of display language</target> |         <target>Use date format of display language</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">96</context> |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |  | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit datatype="html" id="4912706592792948707"> |  | ||||||
|         <source>ISO 8601</source> |  | ||||||
|         <target>ISO 8601</target> |  | ||||||
|         <context-group purpose="location"> |  | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |  | ||||||
|           <context context-type="linenumber">97</context> |  | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="8488620293789898901"> |       <trans-unit datatype="html" id="8488620293789898901"> | ||||||
| @@ -630,7 +622,7 @@ | |||||||
|         <target>Error while storing settings on server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> |         <target>Error while storing settings on server: <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">114</context> |           <context context-type="linenumber">115</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> |       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> | ||||||
| @@ -1832,6 +1824,14 @@ | |||||||
|           <context context-type="linenumber">21</context> |           <context context-type="linenumber">21</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="d6529debfc1613db22d6fa096ebfeb8a85fa739d"> | ||||||
|  |         <source>Invalid date.</source> | ||||||
|  |         <target>Invalid date.</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> | ||||||
|  |           <context context-type="linenumber">13</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2807800733729323332"> |       <trans-unit datatype="html" id="2807800733729323332"> | ||||||
|         <source>Yes</source> |         <source>Yes</source> | ||||||
|         <target>Yes</target> |         <target>Yes</target> | ||||||
| @@ -1861,7 +1861,7 @@ | |||||||
|         <target>English (US)</target> |         <target>English (US)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">82</context> |           <context context-type="linenumber">88</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="6987083569809053351"> |       <trans-unit datatype="html" id="6987083569809053351"> | ||||||
| @@ -1869,7 +1869,7 @@ | |||||||
|         <target>English (GB)</target> |         <target>English (GB)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">83</context> |           <context context-type="linenumber">89</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="1858110241312746425"> |       <trans-unit datatype="html" id="1858110241312746425"> | ||||||
| @@ -1877,7 +1877,7 @@ | |||||||
|         <target>German</target> |         <target>German</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">84</context> |           <context context-type="linenumber">90</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="3071065188816255493"> |       <trans-unit datatype="html" id="3071065188816255493"> | ||||||
| @@ -1885,7 +1885,7 @@ | |||||||
|         <target>Dutch</target> |         <target>Dutch</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">85</context> |           <context context-type="linenumber">91</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7633754075223722162"> |       <trans-unit datatype="html" id="7633754075223722162"> | ||||||
| @@ -1893,7 +1893,23 @@ | |||||||
|         <target>French</target> |         <target>French</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">86</context> |           <context context-type="linenumber">92</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="9184513005098760425"> | ||||||
|  |         <source>Portuguese (Brazil)</source> | ||||||
|  |         <target>Portuguese (Brazil)</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">93</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="4912706592792948707"> | ||||||
|  |         <source>ISO 8601</source> | ||||||
|  |         <target>ISO 8601</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2119857572761283468"> |       <trans-unit datatype="html" id="2119857572761283468"> | ||||||
|   | |||||||
| @@ -606,7 +606,7 @@ | |||||||
|         <target>Utiliser la langue du système</target> |         <target>Utiliser la langue du système</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">91</context> |           <context context-type="linenumber">92</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7729897675462249787"> |       <trans-unit datatype="html" id="7729897675462249787"> | ||||||
| @@ -614,15 +614,7 @@ | |||||||
|         <target>Utiliser le format de date de la langue d'affichage</target> |         <target>Utiliser le format de date de la langue d'affichage</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">96</context> |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |  | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit datatype="html" id="4912706592792948707"> |  | ||||||
|         <source>ISO 8601</source> |  | ||||||
|         <target>ISO 8601</target> |  | ||||||
|         <context-group purpose="location"> |  | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |  | ||||||
|           <context context-type="linenumber">97</context> |  | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="8488620293789898901"> |       <trans-unit datatype="html" id="8488620293789898901"> | ||||||
| @@ -630,7 +622,7 @@ | |||||||
|         <target>Une erreur s'est produite lors de l'enregistrement des paramètres sur le serveur : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> |         <target>Une erreur s'est produite lors de l'enregistrement des paramètres sur le serveur : <x equiv-text="JSON.stringify(error.error)" id="PH"/></target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context> | ||||||
|           <context context-type="linenumber">114</context> |           <context context-type="linenumber">115</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> |       <trans-unit datatype="html" id="121cc5391cd2a5115bc2b3160379ee5b36cd7716"> | ||||||
| @@ -819,7 +811,7 @@ | |||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="8680abbea249ebe9c2fe35556559c8e1a9eb5841"> |       <trans-unit datatype="html" id="8680abbea249ebe9c2fe35556559c8e1a9eb5841"> | ||||||
|         <source>Document processing</source> |         <source>Document processing</source> | ||||||
|         <target>Traitement de document</target> |         <target>Traitement de documents</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> |           <context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context> | ||||||
|           <context context-type="linenumber">118</context> |           <context context-type="linenumber">118</context> | ||||||
| @@ -1832,6 +1824,14 @@ | |||||||
|           <context context-type="linenumber">21</context> |           <context context-type="linenumber">21</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="d6529debfc1613db22d6fa096ebfeb8a85fa739d"> | ||||||
|  |         <source>Invalid date.</source> | ||||||
|  |         <target>Date incorrecte.</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> | ||||||
|  |           <context context-type="linenumber">13</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2807800733729323332"> |       <trans-unit datatype="html" id="2807800733729323332"> | ||||||
|         <source>Yes</source> |         <source>Yes</source> | ||||||
|         <target>Oui</target> |         <target>Oui</target> | ||||||
| @@ -1861,7 +1861,7 @@ | |||||||
|         <target>Anglais (US)</target> |         <target>Anglais (US)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">82</context> |           <context context-type="linenumber">88</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="6987083569809053351"> |       <trans-unit datatype="html" id="6987083569809053351"> | ||||||
| @@ -1869,7 +1869,7 @@ | |||||||
|         <target>Anglais (GB)</target> |         <target>Anglais (GB)</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">83</context> |           <context context-type="linenumber">89</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="1858110241312746425"> |       <trans-unit datatype="html" id="1858110241312746425"> | ||||||
| @@ -1877,7 +1877,7 @@ | |||||||
|         <target>Allemand</target> |         <target>Allemand</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">84</context> |           <context context-type="linenumber">90</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="3071065188816255493"> |       <trans-unit datatype="html" id="3071065188816255493"> | ||||||
| @@ -1885,7 +1885,7 @@ | |||||||
|         <target>Néerlandais</target> |         <target>Néerlandais</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">85</context> |           <context context-type="linenumber">91</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="7633754075223722162"> |       <trans-unit datatype="html" id="7633754075223722162"> | ||||||
| @@ -1893,7 +1893,23 @@ | |||||||
|         <target>Français</target> |         <target>Français</target> | ||||||
|         <context-group purpose="location"> |         <context-group purpose="location"> | ||||||
|           <context context-type="sourcefile">src/app/services/settings.service.ts</context> |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|           <context context-type="linenumber">86</context> |           <context context-type="linenumber">92</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="9184513005098760425"> | ||||||
|  |         <source>Portuguese (Brazil)</source> | ||||||
|  |         <target>Portugais (Brésil)</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">93</context> | ||||||
|  |         </context-group> | ||||||
|  |       </trans-unit> | ||||||
|  |       <trans-unit datatype="html" id="4912706592792948707"> | ||||||
|  |         <source>ISO 8601</source> | ||||||
|  |         <target>ISO 8601</target> | ||||||
|  |         <context-group purpose="location"> | ||||||
|  |           <context context-type="sourcefile">src/app/services/settings.service.ts</context> | ||||||
|  |           <context context-type="linenumber">98</context> | ||||||
|         </context-group> |         </context-group> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit datatype="html" id="2119857572761283468"> |       <trans-unit datatype="html" id="2119857572761283468"> | ||||||
|   | |||||||
							
								
								
									
										2353
									
								
								src-ui/src/locale/messages.pt_BR.xlf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2353
									
								
								src-ui/src/locale/messages.pt_BR.xlf
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -246,6 +246,16 @@ $border-color-dark-mode: #47494f; | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   .btn-light:not(:disabled):not(.disabled) { | ||||||
|  |     background-color: $bg-dark-mode; | ||||||
|  |     color: $text-color-dark-mode-accent; | ||||||
|  |  | ||||||
|  |     &:hover { | ||||||
|  |       background-color: $text-color-dark-mode; | ||||||
|  |       color: $bg-dark-mode; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   .btn-link:not(:disabled):not(.disabled) { |   .btn-link:not(:disabled):not(.disabled) { | ||||||
|     color: $primary-dark-mode; |     color: $primary-dark-mode; | ||||||
|   } |   } | ||||||
| @@ -366,6 +376,12 @@ $border-color-dark-mode: #47494f; | |||||||
|   .progress-bar.bg-primary { |   .progress-bar.bg-primary { | ||||||
|     background-color: darken($primary-dark-mode, 5%) !important; |     background-color: darken($primary-dark-mode, 5%) !important; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   .ngb-dp-header, | ||||||
|  |   .ngb-dp-weekdays, | ||||||
|  |   .ngb-dp-month { | ||||||
|  |     background-color: $bg-light-dark-mode; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| body.color-scheme-dark { | body.color-scheme-dark { | ||||||
|   | |||||||
| @@ -1,11 +1,13 @@ | |||||||
|  | import re | ||||||
|  |  | ||||||
| import magic | import magic | ||||||
| from django.utils.text import slugify | from django.utils.text import slugify | ||||||
| from rest_framework import serializers | from rest_framework import serializers | ||||||
| from rest_framework.fields import SerializerMethodField | from rest_framework.fields import SerializerMethodField | ||||||
|  |  | ||||||
| from . import bulk_edit | from . import bulk_edit | ||||||
| from .models import Correspondent, Tag, Document, Log, DocumentType, \ | from .models import Correspondent, Tag, Document, DocumentType, \ | ||||||
|     SavedView, SavedViewFilterRule |     SavedView, SavedViewFilterRule, MatchingModel | ||||||
| from .parsers import is_mime_type_supported | from .parsers import is_mime_type_supported | ||||||
|  |  | ||||||
| from django.utils.translation import gettext as _ | from django.utils.translation import gettext as _ | ||||||
| @@ -33,16 +35,30 @@ class DynamicFieldsModelSerializer(serializers.ModelSerializer): | |||||||
|                 self.fields.pop(field_name) |                 self.fields.pop(field_name) | ||||||
|  |  | ||||||
|  |  | ||||||
| class CorrespondentSerializer(serializers.ModelSerializer): | class MatchingModelSerializer(serializers.ModelSerializer): | ||||||
|  |  | ||||||
|     document_count = serializers.IntegerField(read_only=True) |     document_count = serializers.IntegerField(read_only=True) | ||||||
|  |  | ||||||
|     last_correspondence = serializers.DateTimeField(read_only=True) |  | ||||||
|  |  | ||||||
|     def get_slug(self, obj): |     def get_slug(self, obj): | ||||||
|         return slugify(obj.name) |         return slugify(obj.name) | ||||||
|     slug = SerializerMethodField() |     slug = SerializerMethodField() | ||||||
|  |  | ||||||
|  |     def validate_match(self, match): | ||||||
|  |         if 'matching_algorithm' in self.initial_data and self.initial_data['matching_algorithm'] == MatchingModel.MATCH_REGEX:  # NOQA: E501 | ||||||
|  |             try: | ||||||
|  |                 re.compile(match) | ||||||
|  |             except Exception as e: | ||||||
|  |                 raise serializers.ValidationError( | ||||||
|  |                     _("Invalid regular expresssion: %(error)s") % | ||||||
|  |                     {'error': str(e)} | ||||||
|  |                 ) | ||||||
|  |         return match | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CorrespondentSerializer(MatchingModelSerializer): | ||||||
|  |  | ||||||
|  |     last_correspondence = serializers.DateTimeField(read_only=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Correspondent |         model = Correspondent | ||||||
|         fields = ( |         fields = ( | ||||||
| @@ -57,13 +73,7 @@ class CorrespondentSerializer(serializers.ModelSerializer): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class DocumentTypeSerializer(serializers.ModelSerializer): | class DocumentTypeSerializer(MatchingModelSerializer): | ||||||
|  |  | ||||||
|     document_count = serializers.IntegerField(read_only=True) |  | ||||||
|  |  | ||||||
|     def get_slug(self, obj): |  | ||||||
|         return slugify(obj.name) |  | ||||||
|     slug = SerializerMethodField() |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = DocumentType |         model = DocumentType | ||||||
| @@ -78,13 +88,7 @@ class DocumentTypeSerializer(serializers.ModelSerializer): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TagSerializer(serializers.ModelSerializer): | class TagSerializer(MatchingModelSerializer): | ||||||
|  |  | ||||||
|     document_count = serializers.IntegerField(read_only=True) |  | ||||||
|  |  | ||||||
|     def get_slug(self, obj): |  | ||||||
|         return slugify(obj.name) |  | ||||||
|     slug = SerializerMethodField() |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Tag |         model = Tag | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ | |||||||
|   <link rel="icon" type="image/x-icon" href="favicon.ico"> |   <link rel="icon" type="image/x-icon" href="favicon.ico"> | ||||||
|   <link rel="manifest" href="{% static webmanifest %}"> |   <link rel="manifest" href="{% static webmanifest %}"> | ||||||
| 	<link rel="stylesheet" href="{% static styles_css %}"> | 	<link rel="stylesheet" href="{% static styles_css %}"> | ||||||
|  | 	<link rel="apple-touch-icon" href="apple-touch-icon.png"> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|   <app-root>{% translate "Paperless-ng is loading..." %}</app-root> |   <app-root>{% translate "Paperless-ng is loading..." %}</app-root> | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ from rest_framework.test import APITestCase | |||||||
| from whoosh.writing import AsyncWriter | from whoosh.writing import AsyncWriter | ||||||
|  |  | ||||||
| from documents import index, bulk_edit | from documents import index, bulk_edit | ||||||
| from documents.models import Document, Correspondent, DocumentType, Tag, SavedView | from documents.models import Document, Correspondent, DocumentType, Tag, SavedView, MatchingModel | ||||||
| from documents.tests.utils import DirectoriesMixin | from documents.tests.utils import DirectoriesMixin | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -772,6 +772,41 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): | |||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|         self.assertListEqual(response.data, ["test", "test2"]) |         self.assertListEqual(response.data, ["test", "test2"]) | ||||||
|  |  | ||||||
|  |     def test_invalid_regex_other_algorithm(self): | ||||||
|  |         for endpoint in ['correspondents', 'tags', 'document_types']: | ||||||
|  |             response = self.client.post(f"/api/{endpoint}/", { | ||||||
|  |                 "name": "test", | ||||||
|  |                 "matching_algorithm": MatchingModel.MATCH_ANY, | ||||||
|  |                 "match": "[" | ||||||
|  |             }, format='json') | ||||||
|  |             self.assertEqual(response.status_code, 201, endpoint) | ||||||
|  |  | ||||||
|  |     def test_invalid_regex(self): | ||||||
|  |         for endpoint in ['correspondents', 'tags', 'document_types']: | ||||||
|  |             response = self.client.post(f"/api/{endpoint}/", { | ||||||
|  |                 "name": "test", | ||||||
|  |                 "matching_algorithm": MatchingModel.MATCH_REGEX, | ||||||
|  |                 "match": "[" | ||||||
|  |             }, format='json') | ||||||
|  |             self.assertEqual(response.status_code, 400, endpoint) | ||||||
|  |  | ||||||
|  |     def test_valid_regex(self): | ||||||
|  |         for endpoint in ['correspondents', 'tags', 'document_types']: | ||||||
|  |             response = self.client.post(f"/api/{endpoint}/", { | ||||||
|  |                 "name": "test", | ||||||
|  |                 "matching_algorithm": MatchingModel.MATCH_REGEX, | ||||||
|  |                 "match": "[0-9]" | ||||||
|  |             }, format='json') | ||||||
|  |             self.assertEqual(response.status_code, 201, endpoint) | ||||||
|  |  | ||||||
|  |     def test_regex_no_algorithm(self): | ||||||
|  |         for endpoint in ['correspondents', 'tags', 'document_types']: | ||||||
|  |             response = self.client.post(f"/api/{endpoint}/", { | ||||||
|  |                 "name": "test", | ||||||
|  |                 "match": "[0-9]" | ||||||
|  |             }, format='json') | ||||||
|  |             self.assertEqual(response.status_code, 201, endpoint) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestBulkEdit(DirectoriesMixin, APITestCase): | class TestBulkEdit(DirectoriesMixin, APITestCase): | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2021-02-16 14:52+0100\n" | "POT-Creation-Date: 2021-02-24 16:49+0100\n" | ||||||
| "PO-Revision-Date: 2021-02-16 18:37+0000\n" | "PO-Revision-Date: 2021-02-16 18:37+0000\n" | ||||||
| "Last-Translator: Jonas Winkler, 2021\n" | "Last-Translator: Jonas Winkler, 2021\n" | ||||||
| "Language-Team: German (https://www.transifex.com/paperless/teams/115905/de/)\n" | "Language-Team: German (https://www.transifex.com/paperless/teams/115905/de/)\n" | ||||||
| @@ -354,7 +354,12 @@ msgstr "Filterregel" | |||||||
| msgid "filter rules" | msgid "filter rules" | ||||||
| msgstr "Filterregeln" | msgstr "Filterregeln" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:370 | #: documents/serialisers.py:52 | ||||||
|  | #, python-format | ||||||
|  | msgid "Invalid regular expresssion: %(error)s" | ||||||
|  | msgstr "Ungültiger regulärer Ausdruck: %(error)s" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:378 | ||||||
| #, python-format | #, python-format | ||||||
| msgid "File type %(type)s not supported" | msgid "File type %(type)s not supported" | ||||||
| msgstr "Dateityp %(type)s nicht unterstützt" | msgstr "Dateityp %(type)s nicht unterstützt" | ||||||
| @@ -421,7 +426,11 @@ msgstr "Niederländisch" | |||||||
| msgid "French" | msgid "French" | ||||||
| msgstr "Französisch" | msgstr "Französisch" | ||||||
|  |  | ||||||
| #: paperless/urls.py:114 | #: paperless/settings.py:296 | ||||||
|  | msgid "Portuguese (Brazil)" | ||||||
|  | msgstr "Portugiesisch (Brasilien)" | ||||||
|  |  | ||||||
|  | #: paperless/urls.py:118 | ||||||
| msgid "Paperless-ng administration" | msgid "Paperless-ng administration" | ||||||
| msgstr "Paperless-ng Administration" | msgstr "Paperless-ng Administration" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2021-02-16 14:52+0100\n" | "POT-Creation-Date: 2021-02-24 16:49+0100\n" | ||||||
| "PO-Revision-Date: 2021-02-16 18:37+0000\n" | "PO-Revision-Date: 2021-02-16 18:37+0000\n" | ||||||
| "Last-Translator: Jonas Winkler, 2021\n" | "Last-Translator: Jonas Winkler, 2021\n" | ||||||
| "Language-Team: English (United Kingdom) (https://www.transifex.com/paperless/teams/115905/en_GB/)\n" | "Language-Team: English (United Kingdom) (https://www.transifex.com/paperless/teams/115905/en_GB/)\n" | ||||||
| @@ -355,7 +355,12 @@ msgstr "filter rule" | |||||||
| msgid "filter rules" | msgid "filter rules" | ||||||
| msgstr "filter rules" | msgstr "filter rules" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:370 | #: documents/serialisers.py:52 | ||||||
|  | #, python-format | ||||||
|  | msgid "Invalid regular expresssion: %(error)s" | ||||||
|  | msgstr "Invalid regular expresssion: %(error)s" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:378 | ||||||
| #, python-format | #, python-format | ||||||
| msgid "File type %(type)s not supported" | msgid "File type %(type)s not supported" | ||||||
| msgstr "File type %(type)s not supported" | msgstr "File type %(type)s not supported" | ||||||
| @@ -420,7 +425,11 @@ msgstr "Dutch" | |||||||
| msgid "French" | msgid "French" | ||||||
| msgstr "French" | msgstr "French" | ||||||
|  |  | ||||||
| #: paperless/urls.py:114 | #: paperless/settings.py:296 | ||||||
|  | msgid "Portuguese (Brazil)" | ||||||
|  | msgstr "Portuguese (Brazil)" | ||||||
|  |  | ||||||
|  | #: paperless/urls.py:118 | ||||||
| msgid "Paperless-ng administration" | msgid "Paperless-ng administration" | ||||||
| msgstr "Paperless-ng administration" | msgstr "Paperless-ng administration" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2021-02-16 14:52+0100\n" | "POT-Creation-Date: 2021-02-24 16:49+0100\n" | ||||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | "Language-Team: LANGUAGE <LL@li.org>\n" | ||||||
| @@ -346,7 +346,12 @@ msgstr "" | |||||||
| msgid "filter rules" | msgid "filter rules" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:370 | #: documents/serialisers.py:52 | ||||||
|  | #, python-format | ||||||
|  | msgid "Invalid regular expresssion: %(error)s" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:378 | ||||||
| #, python-format | #, python-format | ||||||
| msgid "File type %(type)s not supported" | msgid "File type %(type)s not supported" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -411,7 +416,11 @@ msgstr "" | |||||||
| msgid "French" | msgid "French" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: paperless/urls.py:114 | #: paperless/settings.py:296 | ||||||
|  | msgid "Portuguese (Brazil)" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: paperless/urls.py:118 | ||||||
| msgid "Paperless-ng administration" | msgid "Paperless-ng administration" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2021-02-16 14:52+0100\n" | "POT-Creation-Date: 2021-02-24 16:49+0100\n" | ||||||
| "PO-Revision-Date: 2021-02-16 18:37+0000\n" | "PO-Revision-Date: 2021-02-16 18:37+0000\n" | ||||||
| "Last-Translator: Philmo67, 2021\n" | "Last-Translator: Philmo67, 2021\n" | ||||||
| "Language-Team: French (https://www.transifex.com/paperless/teams/115905/fr/)\n" | "Language-Team: French (https://www.transifex.com/paperless/teams/115905/fr/)\n" | ||||||
| @@ -356,7 +356,12 @@ msgstr "règle de filtrage" | |||||||
| msgid "filter rules" | msgid "filter rules" | ||||||
| msgstr "règles de filtrage" | msgstr "règles de filtrage" | ||||||
|  |  | ||||||
| #: documents/serialisers.py:370 | #: documents/serialisers.py:52 | ||||||
|  | #, python-format | ||||||
|  | msgid "Invalid regular expresssion: %(error)s" | ||||||
|  | msgstr "Expression régulière incorrecte : %(error)s" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:378 | ||||||
| #, python-format | #, python-format | ||||||
| msgid "File type %(type)s not supported" | msgid "File type %(type)s not supported" | ||||||
| msgstr "Type de fichier %(type)s non pris en charge" | msgstr "Type de fichier %(type)s non pris en charge" | ||||||
| @@ -423,7 +428,11 @@ msgstr "Néerlandais" | |||||||
| msgid "French" | msgid "French" | ||||||
| msgstr "Français" | msgstr "Français" | ||||||
|  |  | ||||||
| #: paperless/urls.py:114 | #: paperless/settings.py:296 | ||||||
|  | msgid "Portuguese (Brazil)" | ||||||
|  | msgstr "Portugais (Brésil)" | ||||||
|  |  | ||||||
|  | #: paperless/urls.py:118 | ||||||
| msgid "Paperless-ng administration" | msgid "Paperless-ng administration" | ||||||
| msgstr "Administration de Paperless-ng" | msgstr "Administration de Paperless-ng" | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										672
									
								
								src/locale/pt_BR/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										672
									
								
								src/locale/pt_BR/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,672 @@ | |||||||
|  | # SOME DESCRIPTIVE TITLE. | ||||||
|  | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||||||
|  | # This file is distributed under the same license as the PACKAGE package. | ||||||
|  | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||||||
|  | #  | ||||||
|  | # Translators: | ||||||
|  | # Jonas Winkler, 2021 | ||||||
|  | # Rodrigo A <rodrigo.avelino@meliuz.com.br>, 2021 | ||||||
|  | #  | ||||||
|  | #, fuzzy | ||||||
|  | msgid "" | ||||||
|  | msgstr "" | ||||||
|  | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
|  | "Report-Msgid-Bugs-To: \n" | ||||||
|  | "POT-Creation-Date: 2021-02-24 16:49+0100\n" | ||||||
|  | "PO-Revision-Date: 2021-02-16 18:37+0000\n" | ||||||
|  | "Last-Translator: Rodrigo A <rodrigo.avelino@meliuz.com.br>, 2021\n" | ||||||
|  | "Language-Team: Portuguese (Brazil) (https://www.transifex.com/paperless/teams/115905/pt_BR/)\n" | ||||||
|  | "MIME-Version: 1.0\n" | ||||||
|  | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
|  | "Content-Transfer-Encoding: 8bit\n" | ||||||
|  | "Language: pt_BR\n" | ||||||
|  | "Plural-Forms: nplurals=2; plural=(n > 1);\n" | ||||||
|  |  | ||||||
|  | #: documents/apps.py:10 | ||||||
|  | msgid "Documents" | ||||||
|  | msgstr "Documentos" | ||||||
|  |  | ||||||
|  | #: documents/models.py:32 | ||||||
|  | msgid "Any word" | ||||||
|  | msgstr "Qualquer palavra" | ||||||
|  |  | ||||||
|  | #: documents/models.py:33 | ||||||
|  | msgid "All words" | ||||||
|  | msgstr "Todas as palavras" | ||||||
|  |  | ||||||
|  | #: documents/models.py:34 | ||||||
|  | msgid "Exact match" | ||||||
|  | msgstr "Detecção exata" | ||||||
|  |  | ||||||
|  | #: documents/models.py:35 | ||||||
|  | msgid "Regular expression" | ||||||
|  | msgstr "Expressão regular" | ||||||
|  |  | ||||||
|  | #: documents/models.py:36 | ||||||
|  | msgid "Fuzzy word" | ||||||
|  | msgstr "Palavra difusa (fuzzy)" | ||||||
|  |  | ||||||
|  | #: documents/models.py:37 | ||||||
|  | msgid "Automatic" | ||||||
|  | msgstr "Automático" | ||||||
|  |  | ||||||
|  | #: documents/models.py:41 documents/models.py:364 paperless_mail/models.py:25 | ||||||
|  | #: paperless_mail/models.py:109 | ||||||
|  | msgid "name" | ||||||
|  | msgstr "nome" | ||||||
|  |  | ||||||
|  | #: documents/models.py:45 | ||||||
|  | msgid "match" | ||||||
|  | msgstr "detecção" | ||||||
|  |  | ||||||
|  | #: documents/models.py:49 | ||||||
|  | msgid "matching algorithm" | ||||||
|  | msgstr "algoritmo de detecção" | ||||||
|  |  | ||||||
|  | #: documents/models.py:55 | ||||||
|  | msgid "is insensitive" | ||||||
|  | msgstr "diferencia maiúsculas de minúsculas" | ||||||
|  |  | ||||||
|  | #: documents/models.py:74 documents/models.py:134 | ||||||
|  | msgid "correspondent" | ||||||
|  | msgstr "correspondente" | ||||||
|  |  | ||||||
|  | #: documents/models.py:75 | ||||||
|  | msgid "correspondents" | ||||||
|  | msgstr "correspondentes" | ||||||
|  |  | ||||||
|  | #: documents/models.py:97 | ||||||
|  | msgid "color" | ||||||
|  | msgstr "cor" | ||||||
|  |  | ||||||
|  | #: documents/models.py:101 | ||||||
|  | msgid "is inbox tag" | ||||||
|  | msgstr "é etiqueta caixa de entrada" | ||||||
|  |  | ||||||
|  | #: documents/models.py:103 | ||||||
|  | msgid "" | ||||||
|  | "Marks this tag as an inbox tag: All newly consumed documents will be tagged " | ||||||
|  | "with inbox tags." | ||||||
|  | msgstr "" | ||||||
|  | "Marca essa etiqueta como caixa de entrada: Todos os novos documentos " | ||||||
|  | "consumidos terão as etiquetas de caixa de entrada." | ||||||
|  |  | ||||||
|  | #: documents/models.py:108 | ||||||
|  | msgid "tag" | ||||||
|  | msgstr "etiqueta" | ||||||
|  |  | ||||||
|  | #: documents/models.py:109 documents/models.py:165 | ||||||
|  | msgid "tags" | ||||||
|  | msgstr "etiquetas" | ||||||
|  |  | ||||||
|  | #: documents/models.py:115 documents/models.py:147 | ||||||
|  | msgid "document type" | ||||||
|  | msgstr "tipo de documento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:116 | ||||||
|  | msgid "document types" | ||||||
|  | msgstr "tipos de documento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:124 | ||||||
|  | msgid "Unencrypted" | ||||||
|  | msgstr "Não encriptado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:125 | ||||||
|  | msgid "Encrypted with GNU Privacy Guard" | ||||||
|  | msgstr "Encriptado com GNU Privacy Guard" | ||||||
|  |  | ||||||
|  | #: documents/models.py:138 | ||||||
|  | msgid "title" | ||||||
|  | msgstr "título" | ||||||
|  |  | ||||||
|  | #: documents/models.py:151 | ||||||
|  | msgid "content" | ||||||
|  | msgstr "conteúdo" | ||||||
|  |  | ||||||
|  | #: documents/models.py:153 | ||||||
|  | msgid "" | ||||||
|  | "The raw, text-only data of the document. This field is primarily used for " | ||||||
|  | "searching." | ||||||
|  | msgstr "" | ||||||
|  | "O conteúdo de texto bruto do documento. Esse campo é usado principalmente " | ||||||
|  | "para busca." | ||||||
|  |  | ||||||
|  | #: documents/models.py:158 | ||||||
|  | msgid "mime type" | ||||||
|  | msgstr "tipo mime" | ||||||
|  |  | ||||||
|  | #: documents/models.py:169 | ||||||
|  | msgid "checksum" | ||||||
|  | msgstr "some de verificação" | ||||||
|  |  | ||||||
|  | #: documents/models.py:173 | ||||||
|  | msgid "The checksum of the original document." | ||||||
|  | msgstr "A soma de verificação original do documento." | ||||||
|  |  | ||||||
|  | #: documents/models.py:177 | ||||||
|  | msgid "archive checksum" | ||||||
|  | msgstr "Soma de verificação de arquivamento." | ||||||
|  |  | ||||||
|  | #: documents/models.py:182 | ||||||
|  | msgid "The checksum of the archived document." | ||||||
|  | msgstr "A soma de verificação do documento arquivado." | ||||||
|  |  | ||||||
|  | #: documents/models.py:186 documents/models.py:342 | ||||||
|  | msgid "created" | ||||||
|  | msgstr "criado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:190 | ||||||
|  | msgid "modified" | ||||||
|  | msgstr "modificado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:194 | ||||||
|  | msgid "storage type" | ||||||
|  | msgstr "tipo de armazenamento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:202 | ||||||
|  | msgid "added" | ||||||
|  | msgstr "adicionado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:206 | ||||||
|  | msgid "filename" | ||||||
|  | msgstr "nome do arquivo" | ||||||
|  |  | ||||||
|  | #: documents/models.py:212 | ||||||
|  | msgid "Current filename in storage" | ||||||
|  | msgstr "Nome do arquivo atual armazenado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:216 | ||||||
|  | msgid "archive filename" | ||||||
|  | msgstr "nome do arquivo para arquivamento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:222 | ||||||
|  | msgid "Current archive filename in storage" | ||||||
|  | msgstr "Nome do arquivo para arquivamento armazenado" | ||||||
|  |  | ||||||
|  | #: documents/models.py:226 | ||||||
|  | msgid "archive serial number" | ||||||
|  | msgstr "número de sério de arquivamento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:231 | ||||||
|  | msgid "The position of this document in your physical document archive." | ||||||
|  | msgstr "A posição deste documento no seu arquivamento físico." | ||||||
|  |  | ||||||
|  | #: documents/models.py:237 | ||||||
|  | msgid "document" | ||||||
|  | msgstr "documento" | ||||||
|  |  | ||||||
|  | #: documents/models.py:238 | ||||||
|  | msgid "documents" | ||||||
|  | msgstr "documentos" | ||||||
|  |  | ||||||
|  | #: documents/models.py:325 | ||||||
|  | msgid "debug" | ||||||
|  | msgstr "debug" | ||||||
|  |  | ||||||
|  | #: documents/models.py:326 | ||||||
|  | msgid "information" | ||||||
|  | msgstr "informação" | ||||||
|  |  | ||||||
|  | #: documents/models.py:327 | ||||||
|  | msgid "warning" | ||||||
|  | msgstr "aviso" | ||||||
|  |  | ||||||
|  | #: documents/models.py:328 | ||||||
|  | msgid "error" | ||||||
|  | msgstr "erro" | ||||||
|  |  | ||||||
|  | #: documents/models.py:329 | ||||||
|  | msgid "critical" | ||||||
|  | msgstr "crítico" | ||||||
|  |  | ||||||
|  | #: documents/models.py:333 | ||||||
|  | msgid "group" | ||||||
|  | msgstr "grupo" | ||||||
|  |  | ||||||
|  | #: documents/models.py:336 | ||||||
|  | msgid "message" | ||||||
|  | msgstr "mensagem" | ||||||
|  |  | ||||||
|  | #: documents/models.py:339 | ||||||
|  | msgid "level" | ||||||
|  | msgstr "nível" | ||||||
|  |  | ||||||
|  | #: documents/models.py:346 | ||||||
|  | msgid "log" | ||||||
|  | msgstr "log" | ||||||
|  |  | ||||||
|  | #: documents/models.py:347 | ||||||
|  | msgid "logs" | ||||||
|  | msgstr "logs" | ||||||
|  |  | ||||||
|  | #: documents/models.py:358 documents/models.py:408 | ||||||
|  | msgid "saved view" | ||||||
|  | msgstr "visualização" | ||||||
|  |  | ||||||
|  | #: documents/models.py:359 | ||||||
|  | msgid "saved views" | ||||||
|  | msgstr "visualizações" | ||||||
|  |  | ||||||
|  | #: documents/models.py:362 | ||||||
|  | msgid "user" | ||||||
|  | msgstr "usuário" | ||||||
|  |  | ||||||
|  | #: documents/models.py:368 | ||||||
|  | msgid "show on dashboard" | ||||||
|  | msgstr "exibir no painel de controle" | ||||||
|  |  | ||||||
|  | #: documents/models.py:371 | ||||||
|  | msgid "show in sidebar" | ||||||
|  | msgstr "exibir no painel lateral" | ||||||
|  |  | ||||||
|  | #: documents/models.py:375 | ||||||
|  | msgid "sort field" | ||||||
|  | msgstr "ordenar campo" | ||||||
|  |  | ||||||
|  | #: documents/models.py:378 | ||||||
|  | msgid "sort reverse" | ||||||
|  | msgstr "odernar reverso" | ||||||
|  |  | ||||||
|  | #: documents/models.py:384 | ||||||
|  | msgid "title contains" | ||||||
|  | msgstr "título contém" | ||||||
|  |  | ||||||
|  | #: documents/models.py:385 | ||||||
|  | msgid "content contains" | ||||||
|  | msgstr "conteúdo contém" | ||||||
|  |  | ||||||
|  | #: documents/models.py:386 | ||||||
|  | msgid "ASN is" | ||||||
|  | msgstr "NSA é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:387 | ||||||
|  | msgid "correspondent is" | ||||||
|  | msgstr "correspondente é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:388 | ||||||
|  | msgid "document type is" | ||||||
|  | msgstr "tipo de documento é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:389 | ||||||
|  | msgid "is in inbox" | ||||||
|  | msgstr "é caixa de entrada" | ||||||
|  |  | ||||||
|  | #: documents/models.py:390 | ||||||
|  | msgid "has tag" | ||||||
|  | msgstr "contém etiqueta" | ||||||
|  |  | ||||||
|  | #: documents/models.py:391 | ||||||
|  | msgid "has any tag" | ||||||
|  | msgstr "contém qualquer etiqueta" | ||||||
|  |  | ||||||
|  | #: documents/models.py:392 | ||||||
|  | msgid "created before" | ||||||
|  | msgstr "criado antes de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:393 | ||||||
|  | msgid "created after" | ||||||
|  | msgstr "criado depois de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:394 | ||||||
|  | msgid "created year is" | ||||||
|  | msgstr "ano de criação é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:395 | ||||||
|  | msgid "created month is" | ||||||
|  | msgstr "mês de criação é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:396 | ||||||
|  | msgid "created day is" | ||||||
|  | msgstr "dia de criação é" | ||||||
|  |  | ||||||
|  | #: documents/models.py:397 | ||||||
|  | msgid "added before" | ||||||
|  | msgstr "adicionado antes de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:398 | ||||||
|  | msgid "added after" | ||||||
|  | msgstr "adicionado depois de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:399 | ||||||
|  | msgid "modified before" | ||||||
|  | msgstr "modificado antes de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:400 | ||||||
|  | msgid "modified after" | ||||||
|  | msgstr "modificado depois de" | ||||||
|  |  | ||||||
|  | #: documents/models.py:401 | ||||||
|  | msgid "does not have tag" | ||||||
|  | msgstr "não tem etiqueta" | ||||||
|  |  | ||||||
|  | #: documents/models.py:412 | ||||||
|  | msgid "rule type" | ||||||
|  | msgstr "tipo de regra" | ||||||
|  |  | ||||||
|  | #: documents/models.py:416 | ||||||
|  | msgid "value" | ||||||
|  | msgstr "valor" | ||||||
|  |  | ||||||
|  | #: documents/models.py:422 | ||||||
|  | msgid "filter rule" | ||||||
|  | msgstr "regra de filtragem" | ||||||
|  |  | ||||||
|  | #: documents/models.py:423 | ||||||
|  | msgid "filter rules" | ||||||
|  | msgstr "regras de filtragem" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:52 | ||||||
|  | #, python-format | ||||||
|  | msgid "Invalid regular expresssion: %(error)s" | ||||||
|  | msgstr "Expressão regular inválida: %(error)s" | ||||||
|  |  | ||||||
|  | #: documents/serialisers.py:378 | ||||||
|  | #, python-format | ||||||
|  | msgid "File type %(type)s not supported" | ||||||
|  | msgstr "Tipo de arquivo %(type)s não suportado" | ||||||
|  |  | ||||||
|  | #: documents/templates/index.html:20 | ||||||
|  | msgid "Paperless-ng is loading..." | ||||||
|  | msgstr "Paperless-ng está carregando..." | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/logged_out.html:13 | ||||||
|  | msgid "Paperless-ng signed out" | ||||||
|  | msgstr "Paperless-ng saiu" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/logged_out.html:41 | ||||||
|  | msgid "You have been successfully logged out. Bye!" | ||||||
|  | msgstr "Sua sessão foi encerrada com sucesso. Até mais!" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/logged_out.html:42 | ||||||
|  | msgid "Sign in again" | ||||||
|  | msgstr "Entre novamente" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:13 | ||||||
|  | msgid "Paperless-ng sign in" | ||||||
|  | msgstr "Entrar no Paperless-ng" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:42 | ||||||
|  | msgid "Please sign in." | ||||||
|  | msgstr "Por favor, entre na sua conta" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:45 | ||||||
|  | msgid "Your username and password didn't match. Please try again." | ||||||
|  | msgstr "Seu usuário e senha estão incorretos. Por favor, tente novamente." | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:48 | ||||||
|  | msgid "Username" | ||||||
|  | msgstr "Usuário" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:49 | ||||||
|  | msgid "Password" | ||||||
|  | msgstr "Senha" | ||||||
|  |  | ||||||
|  | #: documents/templates/registration/login.html:54 | ||||||
|  | msgid "Sign in" | ||||||
|  | msgstr "Entrar" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:291 | ||||||
|  | msgid "English (US)" | ||||||
|  | msgstr "Inglês (EUA)" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:292 | ||||||
|  | msgid "English (GB)" | ||||||
|  | msgstr "Inglês (GB)" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:293 | ||||||
|  | msgid "German" | ||||||
|  | msgstr "Alemão" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:294 | ||||||
|  | msgid "Dutch" | ||||||
|  | msgstr "Holandês" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:295 | ||||||
|  | msgid "French" | ||||||
|  | msgstr "Francês" | ||||||
|  |  | ||||||
|  | #: paperless/settings.py:296 | ||||||
|  | msgid "Portuguese (Brazil)" | ||||||
|  | msgstr "Português (Brasil)" | ||||||
|  |  | ||||||
|  | #: paperless/urls.py:118 | ||||||
|  | msgid "Paperless-ng administration" | ||||||
|  | msgstr "Administração do Paperless-ng" | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:25 | ||||||
|  | msgid "Filter" | ||||||
|  | msgstr "Filtro" | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:27 | ||||||
|  | msgid "" | ||||||
|  | "Paperless will only process mails that match ALL of the filters given below." | ||||||
|  | msgstr "" | ||||||
|  | "Paperless processará somente e-mails que se encaixam em TODOS os filtros " | ||||||
|  | "abaixo." | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:37 | ||||||
|  | msgid "Actions" | ||||||
|  | msgstr "Ações" | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:39 | ||||||
|  | msgid "" | ||||||
|  | "The action applied to the mail. This action is only performed when documents" | ||||||
|  | " were consumed from the mail. Mails without attachments will remain entirely" | ||||||
|  | " untouched." | ||||||
|  | msgstr "" | ||||||
|  | "A ação se aplica ao e-mail. Essa ação só é executada quando documentos foram" | ||||||
|  | " consumidos do e-mail. E-mails sem anexos permanecerão intactos." | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:46 | ||||||
|  | msgid "Metadata" | ||||||
|  | msgstr "Metadados" | ||||||
|  |  | ||||||
|  | #: paperless_mail/admin.py:48 | ||||||
|  | msgid "" | ||||||
|  | "Assign metadata to documents consumed from this rule automatically. If you " | ||||||
|  | "do not assign tags, types or correspondents here, paperless will still " | ||||||
|  | "process all matching rules that you have defined." | ||||||
|  | msgstr "" | ||||||
|  | "Atribua metadados aos documentos consumidos por esta regra automaticamente. " | ||||||
|  | "Se você não atribuir etiquetas, tipos ou correspondentes aqui, paperless " | ||||||
|  | "ainda sim processará todas as regras de detecção que você definiu." | ||||||
|  |  | ||||||
|  | #: paperless_mail/apps.py:9 | ||||||
|  | msgid "Paperless mail" | ||||||
|  | msgstr "Paperless mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:11 | ||||||
|  | msgid "mail account" | ||||||
|  | msgstr "conta de e-mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:12 | ||||||
|  | msgid "mail accounts" | ||||||
|  | msgstr "contas de e-mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:19 | ||||||
|  | msgid "No encryption" | ||||||
|  | msgstr "Sem encriptação" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:20 | ||||||
|  | msgid "Use SSL" | ||||||
|  | msgstr "Usar SSL" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:21 | ||||||
|  | msgid "Use STARTTLS" | ||||||
|  | msgstr "Usar STARTTLS" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:29 | ||||||
|  | msgid "IMAP server" | ||||||
|  | msgstr "Servidor IMAP" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:33 | ||||||
|  | msgid "IMAP port" | ||||||
|  | msgstr "Porta IMAP" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:36 | ||||||
|  | msgid "" | ||||||
|  | "This is usually 143 for unencrypted and STARTTLS connections, and 993 for " | ||||||
|  | "SSL connections." | ||||||
|  | msgstr "" | ||||||
|  | "É geralmente 143 para não encriptado e conexões STARTTLS, e 993 para " | ||||||
|  | "conexões SSL." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:40 | ||||||
|  | msgid "IMAP security" | ||||||
|  | msgstr "segurança IMAP" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:46 | ||||||
|  | msgid "username" | ||||||
|  | msgstr "usuário" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:50 | ||||||
|  | msgid "password" | ||||||
|  | msgstr "senha" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:60 | ||||||
|  | msgid "mail rule" | ||||||
|  | msgstr "regra de e-mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:61 | ||||||
|  | msgid "mail rules" | ||||||
|  | msgstr "regras de e-mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:67 | ||||||
|  | msgid "Only process attachments." | ||||||
|  | msgstr "Processar somente anexos." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:68 | ||||||
|  | msgid "Process all files, including 'inline' attachments." | ||||||
|  | msgstr "Processar todos os arquivos, incluindo anexos 'inline'." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:78 | ||||||
|  | msgid "Mark as read, don't process read mails" | ||||||
|  | msgstr "Marcar como lido, não processar e-mails lidos" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:79 | ||||||
|  | msgid "Flag the mail, don't process flagged mails" | ||||||
|  | msgstr "Sinalizar o e-mail, não processar e-mails sinalizados" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:80 | ||||||
|  | msgid "Move to specified folder" | ||||||
|  | msgstr "Mover para pasta especificada" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:81 | ||||||
|  | msgid "Delete" | ||||||
|  | msgstr "Excluir" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:88 | ||||||
|  | msgid "Use subject as title" | ||||||
|  | msgstr "Usar assunto como título" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:89 | ||||||
|  | msgid "Use attachment filename as title" | ||||||
|  | msgstr "Usar nome do arquivo anexo como título" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:99 | ||||||
|  | msgid "Do not assign a correspondent" | ||||||
|  | msgstr "Não atribuir um correspondente" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:101 | ||||||
|  | msgid "Use mail address" | ||||||
|  | msgstr "Usar endereço de e-mail" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:103 | ||||||
|  | msgid "Use name (or mail address if not available)" | ||||||
|  | msgstr "Usar nome (ou endereço de e-mail se não disponível)" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:105 | ||||||
|  | msgid "Use correspondent selected below" | ||||||
|  | msgstr "Usar correspondente selecionado abaixo" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:113 | ||||||
|  | msgid "order" | ||||||
|  | msgstr "ordem" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:120 | ||||||
|  | msgid "account" | ||||||
|  | msgstr "conta" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:124 | ||||||
|  | msgid "folder" | ||||||
|  | msgstr "pasta" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:128 | ||||||
|  | msgid "filter from" | ||||||
|  | msgstr "filtrar de" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:131 | ||||||
|  | msgid "filter subject" | ||||||
|  | msgstr "filtrar assunto" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:134 | ||||||
|  | msgid "filter body" | ||||||
|  | msgstr "filtrar corpo" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:138 | ||||||
|  | msgid "filter attachment filename" | ||||||
|  | msgstr "filtrar nome do arquivo anexo" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:140 | ||||||
|  | msgid "" | ||||||
|  | "Only consume documents which entirely match this filename if specified. " | ||||||
|  | "Wildcards such as *.pdf or *invoice* are allowed. Case insensitive." | ||||||
|  | msgstr "" | ||||||
|  | "Consumir somente documentos que correspondem a este nome de arquivo se especificado.\n" | ||||||
|  | "Curingas como *.pdf ou *invoice* são permitidos. Sem diferenciação de maiúsculas e minúsculas." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:146 | ||||||
|  | msgid "maximum age" | ||||||
|  | msgstr "idade máxima" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:148 | ||||||
|  | msgid "Specified in days." | ||||||
|  | msgstr "Especificada em dias." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:151 | ||||||
|  | msgid "attachment type" | ||||||
|  | msgstr "tipo de anexo" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:154 | ||||||
|  | msgid "" | ||||||
|  | "Inline attachments include embedded images, so it's best to combine this " | ||||||
|  | "option with a filename filter." | ||||||
|  | msgstr "" | ||||||
|  | "Anexos inline incluem imagens inseridas, por isso é melhor combinar essa " | ||||||
|  | "opção com um filtro de nome de arquivo." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:159 | ||||||
|  | msgid "action" | ||||||
|  | msgstr "ação" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:165 | ||||||
|  | msgid "action parameter" | ||||||
|  | msgstr "parâmetro da ação" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:167 | ||||||
|  | msgid "" | ||||||
|  | "Additional parameter for the action selected above, i.e., the target folder " | ||||||
|  | "of the move to folder action." | ||||||
|  | msgstr "" | ||||||
|  | "Parâmetro adicional para a ação selecionada acima, por exemplo: a pasta de " | ||||||
|  | "destino da ação de mover pasta." | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:173 | ||||||
|  | msgid "assign title from" | ||||||
|  | msgstr "atribuir título de" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:183 | ||||||
|  | msgid "assign this tag" | ||||||
|  | msgstr "atribuir esta etiqueta" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:191 | ||||||
|  | msgid "assign this document type" | ||||||
|  | msgstr "atribuir este tipo de documento" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:195 | ||||||
|  | msgid "assign correspondent from" | ||||||
|  | msgstr "atribuir correspondente de" | ||||||
|  |  | ||||||
|  | #: paperless_mail/models.py:205 | ||||||
|  | msgid "assign this correspondent" | ||||||
|  | msgstr "atribuir este correspondente" | ||||||
| @@ -112,7 +112,10 @@ REST_FRAMEWORK = { | |||||||
|         'rest_framework.authentication.BasicAuthentication', |         'rest_framework.authentication.BasicAuthentication', | ||||||
|         'rest_framework.authentication.SessionAuthentication', |         'rest_framework.authentication.SessionAuthentication', | ||||||
|         'rest_framework.authentication.TokenAuthentication' |         'rest_framework.authentication.TokenAuthentication' | ||||||
|     ] |     ], | ||||||
|  |     'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning', | ||||||
|  |     'DEFAULT_VERSION': '1', | ||||||
|  |     'ALLOWED_VERSIONS': ['1', '2'] | ||||||
| } | } | ||||||
|  |  | ||||||
| if DEBUG: | if DEBUG: | ||||||
| @@ -142,7 +145,7 @@ ASGI_APPLICATION = "paperless.asgi.application" | |||||||
|  |  | ||||||
| STATIC_URL = os.getenv("PAPERLESS_STATIC_URL", "/static/") | STATIC_URL = os.getenv("PAPERLESS_STATIC_URL", "/static/") | ||||||
|  |  | ||||||
| # what is this used for? | # TODO: what is this used for? | ||||||
| TEMPLATES = [ | TEMPLATES = [ | ||||||
|     { |     { | ||||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', |         'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||||||
| @@ -292,7 +295,8 @@ LANGUAGES = [ | |||||||
|     ("en-gb", _("English (GB)")), |     ("en-gb", _("English (GB)")), | ||||||
|     ("de", _("German")), |     ("de", _("German")), | ||||||
|     ("nl-nl", _("Dutch")), |     ("nl-nl", _("Dutch")), | ||||||
|     ("fr", _("French")) |     ("fr", _("French")), | ||||||
|  |     ("pt-br", _("Portuguese (Brazil)")) | ||||||
| ] | ] | ||||||
|  |  | ||||||
| LOCALE_PATHS = [ | LOCALE_PATHS = [ | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| __version__ = (1, 2, 0) | __version__ = (1, 2, 1) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jonaswinkler
					jonaswinkler