diff options
40 files changed, 278 insertions, 1098 deletions
diff --git a/apps/admin_audit/l10n/es_EC.js b/apps/admin_audit/l10n/es_EC.js new file mode 100644 index 00000000000..f39d29b3ea7 --- /dev/null +++ b/apps/admin_audit/l10n/es_EC.js @@ -0,0 +1,7 @@ +OC.L10N.register( + "admin_audit", + { + "Auditing / Logging" : "Auditoría / Registro", + "Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Proporciona capacidades de registro para Nextcloud, como el registro de accesos a archivos o acciones confidenciales." +}, +"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/apps/admin_audit/l10n/es_EC.json b/apps/admin_audit/l10n/es_EC.json new file mode 100644 index 00000000000..4fb9f38c21f --- /dev/null +++ b/apps/admin_audit/l10n/es_EC.json @@ -0,0 +1,5 @@ +{ "translations": { + "Auditing / Logging" : "Auditoría / Registro", + "Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions." : "Proporciona capacidades de registro para Nextcloud, como el registro de accesos a archivos o acciones confidenciales." +},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" +}
\ No newline at end of file diff --git a/apps/dashboard/l10n/es_EC.js b/apps/dashboard/l10n/es_EC.js new file mode 100644 index 00000000000..d9f3a53a765 --- /dev/null +++ b/apps/dashboard/l10n/es_EC.js @@ -0,0 +1,28 @@ +OC.L10N.register( + "dashboard", + { + "Dashboard" : "Tablero de control", + "Dashboard app" : "App Dashboard", + "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Comienza tu día informado\n\nEl Dashboard de Nextcloud es tu punto de partida del día, dándote un\nresumen de tus próximas citas, emails urgentes, mensajes de chat,\npróximos tickets, últimos tweets y mucho más! Los usuarios pueden agregr widgets\nque le gusten y cambiar el fondo a su gusto.", + "\"{title} icon\"" : "\"icono {title}\"", + "Customize" : "Personalizar", + "Edit widgets" : "Editar widgets", + "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps", + "Weather service" : "Servicio meteorológico", + "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.", + "Weather data from Met.no" : "Datos meteorológicos de Met.no", + "geocoding with Nominatim" : "geocoding con Nominatim", + "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData", + "Weather" : "Clima", + "Status" : "Estatus", + "Good morning" : "Buenos días", + "Good morning, {name}" : "Buenos días, {name}", + "Good afternoon" : "Buenas tardes", + "Good afternoon, {name}" : "Buenas tardes, {name}", + "Good evening" : "Buenas noches", + "Good evening, {name}" : "Buenas noches, {name}", + "Hello" : "Hola", + "Hello, {name}" : "Hola, {name}", + "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Comienza tu día informado\n\nEl Dashboard de Nextcloud es tu punto de partida del día, dándote un\nresumen de tus próximas citas, emails urgentes, mensajes de chat,\npróximos tickets, últimos tweets y mucho más! Los usuarios pueden agregr widgets\nque le gusten y cambiar el fondo a su gusto." +}, +"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/apps/dashboard/l10n/es_EC.json b/apps/dashboard/l10n/es_EC.json new file mode 100644 index 00000000000..5cd3c41b550 --- /dev/null +++ b/apps/dashboard/l10n/es_EC.json @@ -0,0 +1,26 @@ +{ "translations": { + "Dashboard" : "Tablero de control", + "Dashboard app" : "App Dashboard", + "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! Users can add the widgets they like and change the background to their liking." : "Comienza tu día informado\n\nEl Dashboard de Nextcloud es tu punto de partida del día, dándote un\nresumen de tus próximas citas, emails urgentes, mensajes de chat,\npróximos tickets, últimos tweets y mucho más! Los usuarios pueden agregr widgets\nque le gusten y cambiar el fondo a su gusto.", + "\"{title} icon\"" : "\"icono {title}\"", + "Customize" : "Personalizar", + "Edit widgets" : "Editar widgets", + "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps", + "Weather service" : "Servicio meteorológico", + "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.", + "Weather data from Met.no" : "Datos meteorológicos de Met.no", + "geocoding with Nominatim" : "geocoding con Nominatim", + "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData", + "Weather" : "Clima", + "Status" : "Estatus", + "Good morning" : "Buenos días", + "Good morning, {name}" : "Buenos días, {name}", + "Good afternoon" : "Buenas tardes", + "Good afternoon, {name}" : "Buenas tardes, {name}", + "Good evening" : "Buenas noches", + "Good evening, {name}" : "Buenas noches, {name}", + "Hello" : "Hola", + "Hello, {name}" : "Hola, {name}", + "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Comienza tu día informado\n\nEl Dashboard de Nextcloud es tu punto de partida del día, dándote un\nresumen de tus próximas citas, emails urgentes, mensajes de chat,\npróximos tickets, últimos tweets y mucho más! Los usuarios pueden agregr widgets\nque le gusten y cambiar el fondo a su gusto." +},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" +}
\ No newline at end of file diff --git a/apps/dashboard/l10n/fa.js b/apps/dashboard/l10n/fa.js index 15a848cd36c..c2a823ab4b1 100644 --- a/apps/dashboard/l10n/fa.js +++ b/apps/dashboard/l10n/fa.js @@ -3,12 +3,14 @@ OC.L10N.register( { "Dashboard" : "پیشخوان", "Dashboard app" : "برنامه پیشخوان", + "\"{title} icon\"" : "«شکلک {title}»", "Customize" : "سفارشیسازی", "Edit widgets" : "ویرایش ابزارکها", "Get more widgets from the App Store" : "ویجت های بیشتر را از اپ استور دریافت کنید", "Weather service" : "سامانه هواشناسی", "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "برای حفظ حریم خصوصی شما، داده های آب و هوا توسط سرور نکستکلود شما از طرف شما درخواست می شود، بنابراین سرویس آب و هوا هیچ اطلاعات شخصی دریافت نمی کند.", "Weather data from Met.no" : "اطلاعات هواشناسی از Met.no", + "elevation data from OpenTopoData" : "دادههای ارتفاع از OpenTopoData", "Weather" : "آب و هوا", "Status" : "وضعیت", "Good morning" : "صبح بخیر", diff --git a/apps/dashboard/l10n/fa.json b/apps/dashboard/l10n/fa.json index eff0030d59d..ef262e796a5 100644 --- a/apps/dashboard/l10n/fa.json +++ b/apps/dashboard/l10n/fa.json @@ -1,12 +1,14 @@ { "translations": { "Dashboard" : "پیشخوان", "Dashboard app" : "برنامه پیشخوان", + "\"{title} icon\"" : "«شکلک {title}»", "Customize" : "سفارشیسازی", "Edit widgets" : "ویرایش ابزارکها", "Get more widgets from the App Store" : "ویجت های بیشتر را از اپ استور دریافت کنید", "Weather service" : "سامانه هواشناسی", "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "برای حفظ حریم خصوصی شما، داده های آب و هوا توسط سرور نکستکلود شما از طرف شما درخواست می شود، بنابراین سرویس آب و هوا هیچ اطلاعات شخصی دریافت نمی کند.", "Weather data from Met.no" : "اطلاعات هواشناسی از Met.no", + "elevation data from OpenTopoData" : "دادههای ارتفاع از OpenTopoData", "Weather" : "آب و هوا", "Status" : "وضعیت", "Good morning" : "صبح بخیر", diff --git a/apps/dav/openapi.json b/apps/dav/openapi.json index 21a4500db09..d3d3ee93175 100644 --- a/apps/dav/openapi.json +++ b/apps/dav/openapi.json @@ -158,27 +158,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -188,27 +168,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -218,27 +178,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/apps/encryption/l10n/fa.js b/apps/encryption/l10n/fa.js index 5e3f4857ec7..f8e904c5618 100644 --- a/apps/encryption/l10n/fa.js +++ b/apps/encryption/l10n/fa.js @@ -28,6 +28,8 @@ OC.L10N.register( "Bad Signature" : "امضاء نامعتبر", "Missing Signature" : "امضاء از دست رفته", "one-time password for server-side-encryption" : "رمز عبور یک بار برای رمزگذاری سمت سرور", + "Encryption password" : "رمزنگاری گذرواژه", + "The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "مدیریت، رمزنگاری سمت کارساز را فعال کرده است. پروندههای شما با گذرواژه <strong>%s</strong> رمزنگاری شدند.", "Default encryption module" : "ماژول رمزگذاری پیش فرض", "Default encryption module for server-side encryption" : "ماژول رمزگذاری پیش فرض برای رمزگذاری سمت سرور", "Encryption app is enabled but your keys are not initialized, please log-out and log-in again" : "برنامه رمزگذاری فعال شده است اما کلیدهای شما اولیه نیستند، لطفاً از سیستم خارج و دوباره وارد سیستم شوید.", diff --git a/apps/encryption/l10n/fa.json b/apps/encryption/l10n/fa.json index 5b6ae174b79..71286f5bdd7 100644 --- a/apps/encryption/l10n/fa.json +++ b/apps/encryption/l10n/fa.json @@ -26,6 +26,8 @@ "Bad Signature" : "امضاء نامعتبر", "Missing Signature" : "امضاء از دست رفته", "one-time password for server-side-encryption" : "رمز عبور یک بار برای رمزگذاری سمت سرور", + "Encryption password" : "رمزنگاری گذرواژه", + "The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>." : "مدیریت، رمزنگاری سمت کارساز را فعال کرده است. پروندههای شما با گذرواژه <strong>%s</strong> رمزنگاری شدند.", "Default encryption module" : "ماژول رمزگذاری پیش فرض", "Default encryption module for server-side encryption" : "ماژول رمزگذاری پیش فرض برای رمزگذاری سمت سرور", "Encryption app is enabled but your keys are not initialized, please log-out and log-in again" : "برنامه رمزگذاری فعال شده است اما کلیدهای شما اولیه نیستند، لطفاً از سیستم خارج و دوباره وارد سیستم شوید.", diff --git a/apps/files/l10n/ar.js b/apps/files/l10n/ar.js index 5334215fcd2..b1981e701df 100644 --- a/apps/files/l10n/ar.js +++ b/apps/files/l10n/ar.js @@ -49,7 +49,7 @@ OC.L10N.register( "Pending" : "قيد الانتظار", "Unable to determine date" : "تعذر تحديد التاريخ", "This operation is forbidden" : "هذة العملية ممنوعة ", - "This directory is unavailable, please check the logs or contact the administrator" : "هذا المجلد غير متوفر, الرجاء مراجعة سجل الأخطاء أو الاتصال بمدير النظام", + "This directory is unavailable, please check the logs or contact the administrator" : "هذا المجلد غير متوفر، الرجاء مراجعة سجل الأخطاء أو الاتصال بمدير النظام", "Storage is temporarily not available" : "وحدة التخزين غير متوفرة", "Could not move \"{file}\", target exists" : "لا يمكن نقل \"{file}\", الملف موجود بالفعل هناك", "Could not move \"{file}\"" : "لا يمكن نقل \"{file}\"", diff --git a/apps/files/l10n/ar.json b/apps/files/l10n/ar.json index 0f54e7adfed..2fe334a213b 100644 --- a/apps/files/l10n/ar.json +++ b/apps/files/l10n/ar.json @@ -47,7 +47,7 @@ "Pending" : "قيد الانتظار", "Unable to determine date" : "تعذر تحديد التاريخ", "This operation is forbidden" : "هذة العملية ممنوعة ", - "This directory is unavailable, please check the logs or contact the administrator" : "هذا المجلد غير متوفر, الرجاء مراجعة سجل الأخطاء أو الاتصال بمدير النظام", + "This directory is unavailable, please check the logs or contact the administrator" : "هذا المجلد غير متوفر، الرجاء مراجعة سجل الأخطاء أو الاتصال بمدير النظام", "Storage is temporarily not available" : "وحدة التخزين غير متوفرة", "Could not move \"{file}\", target exists" : "لا يمكن نقل \"{file}\", الملف موجود بالفعل هناك", "Could not move \"{file}\"" : "لا يمكن نقل \"{file}\"", diff --git a/apps/files/l10n/sl.js b/apps/files/l10n/sl.js index 1ff4c331af8..e138a2b6f9b 100644 --- a/apps/files/l10n/sl.js +++ b/apps/files/l10n/sl.js @@ -110,6 +110,7 @@ OC.L10N.register( "Upload file" : "Pošlji datoteko", "Recent" : "Nedavne", "This file has the tag {tag}" : "Datoteka je označena z oznako {tag}", + "This file has the tags {firstTags} and {lastTag}" : "Ta datoteka ima oznake {firstTags} in {lastTag}", "Not favorited" : "Ni priljubljeno", "Remove from favorites" : "Odstrani iz priljubljenih", "Add to favorites" : "Dodaj med priljubljene", @@ -169,10 +170,17 @@ OC.L10N.register( "in %s" : "v %s", "File Management" : "Upravljanje datotek", "Reload current directory" : "Ponovno naloži trenutno mapo", + "Go to the \"{dir}\" directory" : "Pojdi v mapo »{dir}«", + "Select the row for {displayName}" : "Izbor vrstice za {displayName}", "Open folder {name}" : "Odpri mapo {name}", "Download file {name}" : "Prejmi datoteko {name}", + "\"{displayName}\" action executed successfully" : "Dejanje »{displayName}« je uspešno izvedeno", + "\"{displayName}\" action failed" : "Dejanje »{displayName}« je spodletelo", + "Total rows summary" : "Skupni povzetek vrstic", "Select all" : "izberi vse", "Unselect all" : "Odstrani izbor", + "\"{displayName}\" failed on some elements " : "Dejanje »{displayName}« je pri nekaterih predmetih spodletelo", + "\"{displayName}\" batch action executed successfully" : "Paketno dejanje »{displayName}« je uspešno izvedeno", "ascending" : "naraščajoče", "descending" : "padajoče", "Sort list by {column} ({direction})" : "Razvrsti seznam po stolpcu {column} ({direction})", @@ -190,13 +198,17 @@ OC.L10N.register( "Invalid path selected" : "Izbrana je neveljavna pot", "Unknown error" : "Neznana napaka", "Ownership transfer request sent" : "Zahteva za prenos lastništva je poslana", + "Cannot transfer ownership of a file or folder you do not own" : "Ni mogoče prenesti lastništva datotek in map, katerih niste lastnik", "Select file or folder to link to" : "Izbor datoteke ali mape za povezavo", "Loading current folder" : "Poteka nalaganje trenutne mape", "No files in here" : "V mapi ni datotek", + "No files or folders have been deleted yet" : "Ni še izbrisanih datotek in map", "Go to the previous folder" : "Skoči na predhodno mapo", "Go back" : "Skoči nazaj", + "Open the files app settings" : "Odpri nastavitve programa Datoteke", "Files settings" : "Nastavitve datotek", "File cannot be accessed" : "Do datoteke dostop ni mogoč", + "You might not have have permissions to view it, ask the sender to share it" : "Morda ni ustreznih dovoljenj za ogled. Prosite pošiljatelja za prilagoditev.", "Show hidden files" : "Pokaži skrite datoteke", "Crop image previews" : "Obreži slike predogleda", "Additional settings" : "Dodatne nastavitve", diff --git a/apps/files/l10n/sl.json b/apps/files/l10n/sl.json index 0ebe0048dda..725d6b10864 100644 --- a/apps/files/l10n/sl.json +++ b/apps/files/l10n/sl.json @@ -108,6 +108,7 @@ "Upload file" : "Pošlji datoteko", "Recent" : "Nedavne", "This file has the tag {tag}" : "Datoteka je označena z oznako {tag}", + "This file has the tags {firstTags} and {lastTag}" : "Ta datoteka ima oznake {firstTags} in {lastTag}", "Not favorited" : "Ni priljubljeno", "Remove from favorites" : "Odstrani iz priljubljenih", "Add to favorites" : "Dodaj med priljubljene", @@ -167,10 +168,17 @@ "in %s" : "v %s", "File Management" : "Upravljanje datotek", "Reload current directory" : "Ponovno naloži trenutno mapo", + "Go to the \"{dir}\" directory" : "Pojdi v mapo »{dir}«", + "Select the row for {displayName}" : "Izbor vrstice za {displayName}", "Open folder {name}" : "Odpri mapo {name}", "Download file {name}" : "Prejmi datoteko {name}", + "\"{displayName}\" action executed successfully" : "Dejanje »{displayName}« je uspešno izvedeno", + "\"{displayName}\" action failed" : "Dejanje »{displayName}« je spodletelo", + "Total rows summary" : "Skupni povzetek vrstic", "Select all" : "izberi vse", "Unselect all" : "Odstrani izbor", + "\"{displayName}\" failed on some elements " : "Dejanje »{displayName}« je pri nekaterih predmetih spodletelo", + "\"{displayName}\" batch action executed successfully" : "Paketno dejanje »{displayName}« je uspešno izvedeno", "ascending" : "naraščajoče", "descending" : "padajoče", "Sort list by {column} ({direction})" : "Razvrsti seznam po stolpcu {column} ({direction})", @@ -188,13 +196,17 @@ "Invalid path selected" : "Izbrana je neveljavna pot", "Unknown error" : "Neznana napaka", "Ownership transfer request sent" : "Zahteva za prenos lastništva je poslana", + "Cannot transfer ownership of a file or folder you do not own" : "Ni mogoče prenesti lastništva datotek in map, katerih niste lastnik", "Select file or folder to link to" : "Izbor datoteke ali mape za povezavo", "Loading current folder" : "Poteka nalaganje trenutne mape", "No files in here" : "V mapi ni datotek", + "No files or folders have been deleted yet" : "Ni še izbrisanih datotek in map", "Go to the previous folder" : "Skoči na predhodno mapo", "Go back" : "Skoči nazaj", + "Open the files app settings" : "Odpri nastavitve programa Datoteke", "Files settings" : "Nastavitve datotek", "File cannot be accessed" : "Do datoteke dostop ni mogoč", + "You might not have have permissions to view it, ask the sender to share it" : "Morda ni ustreznih dovoljenj za ogled. Prosite pošiljatelja za prilagoditev.", "Show hidden files" : "Pokaži skrite datoteke", "Crop image previews" : "Obreži slike predogleda", "Additional settings" : "Dodatne nastavitve", diff --git a/apps/files/l10n/zh_CN.js b/apps/files/l10n/zh_CN.js index 4d5a70d80fd..c15a252f04d 100644 --- a/apps/files/l10n/zh_CN.js +++ b/apps/files/l10n/zh_CN.js @@ -228,6 +228,7 @@ OC.L10N.register( "Blank" : "空白", "Unable to create new file from template" : "无法从模板创建新文件", "Delete permanently" : "彻底删除", + "Open folder {displayName}" : "打开文件夹{displayName}", "Set up templates folder" : "设置模板文件夹", "Templates" : "模板", "Create new templates folder" : "新建模板文件夹", diff --git a/apps/files/l10n/zh_CN.json b/apps/files/l10n/zh_CN.json index b0c3f12393b..1435ba9b39b 100644 --- a/apps/files/l10n/zh_CN.json +++ b/apps/files/l10n/zh_CN.json @@ -226,6 +226,7 @@ "Blank" : "空白", "Unable to create new file from template" : "无法从模板创建新文件", "Delete permanently" : "彻底删除", + "Open folder {displayName}" : "打开文件夹{displayName}", "Set up templates folder" : "设置模板文件夹", "Templates" : "模板", "Create new templates folder" : "新建模板文件夹", diff --git a/apps/files_sharing/l10n/ko.js b/apps/files_sharing/l10n/ko.js index deb47cc247e..ab2fd831e0b 100644 --- a/apps/files_sharing/l10n/ko.js +++ b/apps/files_sharing/l10n/ko.js @@ -119,6 +119,8 @@ OC.L10N.register( "Reject" : "거절", "This application enables users to share files within Nextcloud. If enabled, the admin can choose which groups can share files. The applicable users can then share files and folders with other users and groups within Nextcloud. In addition, if the admin enables the share link feature, an external link can be used to share files with other users outside of Nextcloud. Admins can also enforce passwords, expirations dates, and enable server to server sharing via share links, as well as sharing from mobile devices.\nTurning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation." : "이 앱을 사용하여 Nextcloud 내에서 사용자간 파일을 공유할 수 있습니다. 앱을 활성화하면 관리자가 파일 공유를 허용할 그룹을 지정할 수 있습니다. 공유가 허용된 사용자는 Nextcloud 내의 다른 사용자나 그룹과 파일이나 폴더를 공유할 수 있습니다. 추가로 관리자가 링크 공유 기능을 활성화하면 Nextcloud 외부 사용자와 파일을 공유할 수 있는 외부 링크가 생성됩니다. 관리자는 암호나 만료 날짜 사용을 강제할 수 있으며, 공유 링크로 서버간 공유 기능이나 모바일 장치에서 공유를 활성화할 수 있습니다.\n공유 기능을 비활성화하면 서버에 있는 모든 공유된 파일이나 폴더를 삭제하며, 동기화 클라이언트나 모바일 앱에도 적용됩니다. 자세한 정보를 보려면 Nextcloud 문서를 참조하십시오.", "Sharing" : "공유", + "Accept user and group shares by default" : "사용자 공유나 그룹 공유를 기본으로 허용함", + "Set default folder for accepted shares" : "허용한 공유의 기본 경로 설정", "Reset" : "초기화", "Invalid path selected" : "잘못된 경로가 선택됨", "Unknown error" : "알 수 없는 오류", diff --git a/apps/files_sharing/l10n/ko.json b/apps/files_sharing/l10n/ko.json index 46e9bd455eb..acce7832d22 100644 --- a/apps/files_sharing/l10n/ko.json +++ b/apps/files_sharing/l10n/ko.json @@ -117,6 +117,8 @@ "Reject" : "거절", "This application enables users to share files within Nextcloud. If enabled, the admin can choose which groups can share files. The applicable users can then share files and folders with other users and groups within Nextcloud. In addition, if the admin enables the share link feature, an external link can be used to share files with other users outside of Nextcloud. Admins can also enforce passwords, expirations dates, and enable server to server sharing via share links, as well as sharing from mobile devices.\nTurning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation." : "이 앱을 사용하여 Nextcloud 내에서 사용자간 파일을 공유할 수 있습니다. 앱을 활성화하면 관리자가 파일 공유를 허용할 그룹을 지정할 수 있습니다. 공유가 허용된 사용자는 Nextcloud 내의 다른 사용자나 그룹과 파일이나 폴더를 공유할 수 있습니다. 추가로 관리자가 링크 공유 기능을 활성화하면 Nextcloud 외부 사용자와 파일을 공유할 수 있는 외부 링크가 생성됩니다. 관리자는 암호나 만료 날짜 사용을 강제할 수 있으며, 공유 링크로 서버간 공유 기능이나 모바일 장치에서 공유를 활성화할 수 있습니다.\n공유 기능을 비활성화하면 서버에 있는 모든 공유된 파일이나 폴더를 삭제하며, 동기화 클라이언트나 모바일 앱에도 적용됩니다. 자세한 정보를 보려면 Nextcloud 문서를 참조하십시오.", "Sharing" : "공유", + "Accept user and group shares by default" : "사용자 공유나 그룹 공유를 기본으로 허용함", + "Set default folder for accepted shares" : "허용한 공유의 기본 경로 설정", "Reset" : "초기화", "Invalid path selected" : "잘못된 경로가 선택됨", "Unknown error" : "알 수 없는 오류", diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json index 00cc171d5d9..59f94c5a5ea 100644 --- a/apps/files_sharing/openapi.json +++ b/apps/files_sharing/openapi.json @@ -1473,27 +1473,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1662,27 +1642,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1692,27 +1652,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1722,27 +1662,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1824,27 +1744,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1854,27 +1754,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2025,27 +1905,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2204,27 +2064,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2234,27 +2074,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2264,27 +2084,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2362,27 +2162,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2392,27 +2172,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2492,27 +2252,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2522,27 +2262,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2685,27 +2405,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2831,27 +2531,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3136,27 +2816,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3235,27 +2895,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3335,27 +2975,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3434,27 +3054,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3464,27 +3064,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/apps/provisioning_api/openapi.json b/apps/provisioning_api/openapi.json index 70515312003..82ee9b16e31 100644 --- a/apps/provisioning_api/openapi.json +++ b/apps/provisioning_api/openapi.json @@ -1227,27 +1227,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1257,27 +1237,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1971,27 +1931,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/apps/settings/l10n/ar.js b/apps/settings/l10n/ar.js index 2dc05771bf6..91d822a073f 100644 --- a/apps/settings/l10n/ar.js +++ b/apps/settings/l10n/ar.js @@ -121,7 +121,7 @@ OC.L10N.register( "Copy" : "نسخ", "Profile" : "الملف الشخصي", "Enable" : "تفعيل", - "Server-side encryption" : "التشفير مِن جانب الخادوم", + "Server-side encryption" : "التشفير مِن جانب الخادم", "Enable server-side encryption" : "تشغيل التشفير مِن جانب الخادوم", "Once encryption is enabled, all files uploaded to the server from that point forward will be encrypted at rest on the server. It will only be possible to disable encryption at a later date if the active encryption module supports that function, and all pre-conditions (e.g. setting a recover key) are met." : "في حال تفعيل التشفير، عملية رفع الملف المشفر سيتم تفعيلها في الخادم. يمكن تعطيل التشفير في وقت لاحق فقط اذا كانت حزمة التشفير المفعلة تدعم التعطيل، وجميع الشروط الاخرى (على سبيل المثال اعداد رمز الاستعادة) مشمول ضمن الحزمة.", "Encryption alone does not guarantee security of the system. Please see documentation for more information about how the encryption app works, and the supported use cases." : "التشفير لوحدها لا تضمن حماية النظام بشكل كامل. يرجى اتباع التعليمات لمزيد من المعلومات والحصول على معلومات عن عمل تطبيق التشفير، واستخداماته العديد.", @@ -139,7 +139,7 @@ OC.L10N.register( "Details" : "التفاصيل", "You are a member of the following groups:" : "إنك عضو في الفِرَق التالية:", "Your email address" : "عنوانك البريدي", - "No email address set" : "لم يتم إدخال أي عنوان للبريد الإلكتروني", + "No email address set" : "لم يتم تعيين بريد الكتروني", "Language" : "اللغة", "Help translate" : "ساعد في الترجمة", "Your phone number" : "رقم هاتفك", diff --git a/apps/settings/l10n/ar.json b/apps/settings/l10n/ar.json index fb490b85f8f..e855cff461b 100644 --- a/apps/settings/l10n/ar.json +++ b/apps/settings/l10n/ar.json @@ -119,7 +119,7 @@ "Copy" : "نسخ", "Profile" : "الملف الشخصي", "Enable" : "تفعيل", - "Server-side encryption" : "التشفير مِن جانب الخادوم", + "Server-side encryption" : "التشفير مِن جانب الخادم", "Enable server-side encryption" : "تشغيل التشفير مِن جانب الخادوم", "Once encryption is enabled, all files uploaded to the server from that point forward will be encrypted at rest on the server. It will only be possible to disable encryption at a later date if the active encryption module supports that function, and all pre-conditions (e.g. setting a recover key) are met." : "في حال تفعيل التشفير، عملية رفع الملف المشفر سيتم تفعيلها في الخادم. يمكن تعطيل التشفير في وقت لاحق فقط اذا كانت حزمة التشفير المفعلة تدعم التعطيل، وجميع الشروط الاخرى (على سبيل المثال اعداد رمز الاستعادة) مشمول ضمن الحزمة.", "Encryption alone does not guarantee security of the system. Please see documentation for more information about how the encryption app works, and the supported use cases." : "التشفير لوحدها لا تضمن حماية النظام بشكل كامل. يرجى اتباع التعليمات لمزيد من المعلومات والحصول على معلومات عن عمل تطبيق التشفير، واستخداماته العديد.", @@ -137,7 +137,7 @@ "Details" : "التفاصيل", "You are a member of the following groups:" : "إنك عضو في الفِرَق التالية:", "Your email address" : "عنوانك البريدي", - "No email address set" : "لم يتم إدخال أي عنوان للبريد الإلكتروني", + "No email address set" : "لم يتم تعيين بريد الكتروني", "Language" : "اللغة", "Help translate" : "ساعد في الترجمة", "Your phone number" : "رقم هاتفك", diff --git a/apps/settings/l10n/ko.js b/apps/settings/l10n/ko.js index 467ab75ab56..2c110478ebc 100644 --- a/apps/settings/l10n/ko.js +++ b/apps/settings/l10n/ko.js @@ -261,6 +261,8 @@ OC.L10N.register( "Your biography" : "내 소개문구", "Details" : "자세히", "You are a member of the following groups:" : "당신은 다음 그룹의 멤버입니다:", + "You are using <strong>{usage}</strong>" : "<strong>{usage}</strong>를 사용하고 있습니다.", + "You are using <strong>{usage}</strong> of <strong>{totalSpace}</strong> (<strong>{usageRelative}%</strong>)" : "전체 <strong>{totalSpace}</strong> 중 <strong>{usage}</strong>(<strong>{usageRelative}%</strong>)를 사용하고 있습니다.", "Your full name" : "내 전체 이름", "Email options" : "이메일 옵션", "Primary email for password reset and notifications" : "암호 초기화 및 알림 수신용 주 이메일 주소", @@ -284,11 +286,14 @@ OC.L10N.register( "Unable to update language" : "언어를 갱신할 수 없음", "No language set" : "언어가 설정되지 않음", "Locale" : "지역", + "Week starts on {firstDayOfWeek}" : "일주일이 {firstDayOfWeek}에 시작함", + "Your location" : "내 위치", "Your organisation" : "내 조직", "Your phone number" : "내 휴대폰 번호", "Edit your Profile visibility" : "프로필 표시 여부 편집", "Enable Profile" : "프로필 활성화", "Unable to update profile enabled state" : "프로필 활성화 여부를 갱신할 수 없음", + "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "표시 여부나 표시 범위 설정은 더 좁은 쪽이 우선 적용됩니다. 예를 들어, 표시 여부는 \"전체 공개\", 표시 범위는 \"개인\"으로 설정되어 있다면, 해당 항목은 \"개인\"에게만 보여집니다.", "Unable to update visibility of {displayId}" : "{displayId}의 표시 여부를 갱신할 수 없음", "Your role" : "내 직책", "Your Twitter handle" : "내 트위터", diff --git a/apps/settings/l10n/ko.json b/apps/settings/l10n/ko.json index 1ac6952a6e3..554d228786e 100644 --- a/apps/settings/l10n/ko.json +++ b/apps/settings/l10n/ko.json @@ -259,6 +259,8 @@ "Your biography" : "내 소개문구", "Details" : "자세히", "You are a member of the following groups:" : "당신은 다음 그룹의 멤버입니다:", + "You are using <strong>{usage}</strong>" : "<strong>{usage}</strong>를 사용하고 있습니다.", + "You are using <strong>{usage}</strong> of <strong>{totalSpace}</strong> (<strong>{usageRelative}%</strong>)" : "전체 <strong>{totalSpace}</strong> 중 <strong>{usage}</strong>(<strong>{usageRelative}%</strong>)를 사용하고 있습니다.", "Your full name" : "내 전체 이름", "Email options" : "이메일 옵션", "Primary email for password reset and notifications" : "암호 초기화 및 알림 수신용 주 이메일 주소", @@ -282,11 +284,14 @@ "Unable to update language" : "언어를 갱신할 수 없음", "No language set" : "언어가 설정되지 않음", "Locale" : "지역", + "Week starts on {firstDayOfWeek}" : "일주일이 {firstDayOfWeek}에 시작함", + "Your location" : "내 위치", "Your organisation" : "내 조직", "Your phone number" : "내 휴대폰 번호", "Edit your Profile visibility" : "프로필 표시 여부 편집", "Enable Profile" : "프로필 활성화", "Unable to update profile enabled state" : "프로필 활성화 여부를 갱신할 수 없음", + "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "표시 여부나 표시 범위 설정은 더 좁은 쪽이 우선 적용됩니다. 예를 들어, 표시 여부는 \"전체 공개\", 표시 범위는 \"개인\"으로 설정되어 있다면, 해당 항목은 \"개인\"에게만 보여집니다.", "Unable to update visibility of {displayId}" : "{displayId}의 표시 여부를 갱신할 수 없음", "Your role" : "내 직책", "Your Twitter handle" : "내 트위터", diff --git a/apps/theming/l10n/ko.js b/apps/theming/l10n/ko.js index 59de0a466aa..3aac6e95760 100644 --- a/apps/theming/l10n/ko.js +++ b/apps/theming/l10n/ko.js @@ -53,7 +53,10 @@ OC.L10N.register( "Upload new favicon" : "새 파비콘 업로드", "User settings" : "사용자 설정", "Keyboard shortcuts" : "키보드 단축키", + "In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "특정 상황에서, 키보드 단축키는 접근성 도구의 동작과 간섭을 일으킬 수 있습니다. 간섭 방지와 접근성 도구의 정확한 동작을 위해, 이곳에서 모든 키보드 단축키를 비활성화할 수 있습니다. 이는 앱에서 사용할 수 있는 모든 단축키 또한 비활성화합니다.", + "Disable all keyboard shortcuts" : "모든 키보드 단축키 비활성화", "Background" : "배경", + "Set a custom background" : "나만의 배경화면 설정", "Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "보편적 접근성은 매우 중요합니다. 저희는 웹 표준을 준수하며, 마우스 혹은 스크린리더와 같은 보조 소프트웨어 없이도 정상적인 사용이 가능한지에 대해 확인하고 있습니다. 또한, {guidelines}웹 컨텐츠 접근성 가이드라인{linkend} 2.1을 AA 수준 및 AAA 수준의 고대비 테마에서 준수하기 위해 노력하고 있습니다. ", "If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "사용 중 문제가 발생했을 경우, {issuetracker}이슈 트래커{linkend}에 보고해주시기 바랍니다. 또한 디자인 부분에 참여하고 싶다면, {designteam}저희 디자인 팀{linkend}과 함께해주세요!", "Change color" : "색깔 바꾸기", diff --git a/apps/theming/l10n/ko.json b/apps/theming/l10n/ko.json index 95b05b6e64f..a1dfc51f901 100644 --- a/apps/theming/l10n/ko.json +++ b/apps/theming/l10n/ko.json @@ -51,7 +51,10 @@ "Upload new favicon" : "새 파비콘 업로드", "User settings" : "사용자 설정", "Keyboard shortcuts" : "키보드 단축키", + "In some cases keyboard shortcuts can interfere with accessibility tools. In order to allow focusing on your tool correctly you can disable all keyboard shortcuts here. This will also disable all available shortcuts in apps." : "특정 상황에서, 키보드 단축키는 접근성 도구의 동작과 간섭을 일으킬 수 있습니다. 간섭 방지와 접근성 도구의 정확한 동작을 위해, 이곳에서 모든 키보드 단축키를 비활성화할 수 있습니다. 이는 앱에서 사용할 수 있는 모든 단축키 또한 비활성화합니다.", + "Disable all keyboard shortcuts" : "모든 키보드 단축키 비활성화", "Background" : "배경", + "Set a custom background" : "나만의 배경화면 설정", "Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level." : "보편적 접근성은 매우 중요합니다. 저희는 웹 표준을 준수하며, 마우스 혹은 스크린리더와 같은 보조 소프트웨어 없이도 정상적인 사용이 가능한지에 대해 확인하고 있습니다. 또한, {guidelines}웹 컨텐츠 접근성 가이드라인{linkend} 2.1을 AA 수준 및 AAA 수준의 고대비 테마에서 준수하기 위해 노력하고 있습니다. ", "If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!" : "사용 중 문제가 발생했을 경우, {issuetracker}이슈 트래커{linkend}에 보고해주시기 바랍니다. 또한 디자인 부분에 참여하고 싶다면, {designteam}저희 디자인 팀{linkend}과 함께해주세요!", "Change color" : "색깔 바꾸기", diff --git a/apps/theming/openapi.json b/apps/theming/openapi.json index 298ec5722d5..9ba6919161f 100644 --- a/apps/theming/openapi.json +++ b/apps/theming/openapi.json @@ -654,28 +654,8 @@ "content": { "*/*": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string", - "format": "binary" - } - } - } - } + "type": "string", + "format": "binary" } } } @@ -685,27 +665,7 @@ "content": { "text/html": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -772,27 +732,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Background" - } - } - } - } + "$ref": "#/components/schemas/Background" } } } @@ -804,31 +744,11 @@ "schema": { "type": "object", "required": [ - "ocs" + "error" ], "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string" - } - } - } - } + "error": { + "type": "string" } } } @@ -842,31 +762,11 @@ "schema": { "type": "object", "required": [ - "ocs" + "error" ], "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string" - } - } - } - } + "error": { + "type": "string" } } } @@ -908,27 +808,7 @@ "content": { "application/json": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "$ref": "#/components/schemas/Background" - } - } - } - } + "$ref": "#/components/schemas/Background" } } } @@ -1008,27 +888,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1038,27 +898,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1138,27 +978,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -1168,27 +988,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/apps/user_status/openapi.json b/apps/user_status/openapi.json index 9a3b67fb2c8..08eddd47bb3 100644 --- a/apps/user_status/openapi.json +++ b/apps/user_status/openapi.json @@ -349,27 +349,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -439,27 +419,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -538,27 +498,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -647,27 +587,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -765,27 +685,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/core/l10n/de_DE.js b/core/l10n/de_DE.js index 9af9bb0b466..da85845d310 100644 --- a/core/l10n/de_DE.js +++ b/core/l10n/de_DE.js @@ -168,7 +168,7 @@ OC.L10N.register( "Your connection is not secure" : "Ihre Verbindung ist nicht sicher", "Passwordless authentication is only available over a secure connection." : "Anmeldung ohne Passwort ist nur über eine sichere Verbindung möglich", "Reset password" : "Passwort zurücksetzen", - "If this account exists, a password reset message has been sent to its email address. If you do not receive it, verify your email address and/or account name, check your spam/junk folders or ask your local administration for help." : "Sofern dieses Konto existiert, wurde eine Nachricht zum Zurücksetzen des Passworts die hinterlegte E-Mail-Adresse gesendet. Wenn Sie diese E-Mail nicht erhalten, überprüfen Sie Ihre E-Mail-Adresse und/oder Ihren Kontonamen sowie Ihren Spam-/Junk-Ordner oder bitten Sie Ihre lokale Administration um Hilfe.", + "If this account exists, a password reset message has been sent to its email address. If you do not receive it, verify your email address and/or account name, check your spam/junk folders or ask your local administration for help." : "Sofern dieses Konto existiert, wurde eine Nachricht zum Zurücksetzen des Passworts an die hinterlegte E-Mail-Adresse gesendet. Wenn Sie diese E-Mail nicht erhalten, überprüfen Sie Ihre E-Mail-Adresse und/oder Ihren Kontonamen sowie Ihren Spam-/Junk-Ordner oder bitten Sie Ihre lokale Administration um Hilfe.", "Couldn't send reset email. Please contact your administrator." : "Die E-Mail zum Zurücksetzen konnte nicht versendet werden. Bitte kontaktieren Sie Ihre Administration.", "Password cannot be changed. Please contact your administrator." : "Passwort kann nicht geändert werden. Bitte kontaktieren Sie Ihren Administrator.", "Back to login" : "Zurück zur Anmeldung", @@ -270,7 +270,7 @@ OC.L10N.register( "Authentication required" : "Legitimierung benötigt", "This action requires you to confirm your password" : "Dieser Vorgang benötigt eine Passwortbestätigung von Ihnen", "Confirm" : "Bestätigen", - "Failed to authenticate, try again" : "Legitimierung fehlgeschlagen, bitte erneut versuchen.", + "Failed to authenticate, try again" : "Authentifizierung fehlgeschlagen, bitte erneut versuchen.", "seconds ago" : "Gerade eben", "Connection to server lost" : "Verbindung zum Server verloren", "_Problem loading page, reloading in %n second_::_Problem loading page, reloading in %n seconds_" : ["Problem beim Laden der Seite, Seite wird in %n Sekunde nochmals geladen","Problem beim Laden der Seite. Seite wird in %n Sekunden erneut geladen"], @@ -310,7 +310,7 @@ OC.L10N.register( "The profile does not exist." : "Das Profil existiert nicht.", "Back to %s" : "Zurück zu %s", "Page not found" : "Seite nicht gefunden", - "The page could not be found on the server or you may not be allowed to view it." : "Die Seite konnte auf dem Server nicht gefunden werden oder Sie sind nicht berechtigt sie anzeigen.", + "The page could not be found on the server or you may not be allowed to view it." : "Die Seite konnte auf dem Server nicht gefunden werden oder Sie sind nicht zum Anzeigen berechtigt.", "Too many requests" : "Zu viele Anfragen", "There were too many requests from your network. Retry later or contact your administrator if this is an error." : "Zu viele Anfragen aus Ihrem Netzwerk. Versuchen Sie es später erneut oder wenden Sie sich an Ihren Administrator, wenn dies ein Fehler sein sollte.", "Error" : "Fehler", diff --git a/core/l10n/de_DE.json b/core/l10n/de_DE.json index a079de0f8df..42eccb4253c 100644 --- a/core/l10n/de_DE.json +++ b/core/l10n/de_DE.json @@ -166,7 +166,7 @@ "Your connection is not secure" : "Ihre Verbindung ist nicht sicher", "Passwordless authentication is only available over a secure connection." : "Anmeldung ohne Passwort ist nur über eine sichere Verbindung möglich", "Reset password" : "Passwort zurücksetzen", - "If this account exists, a password reset message has been sent to its email address. If you do not receive it, verify your email address and/or account name, check your spam/junk folders or ask your local administration for help." : "Sofern dieses Konto existiert, wurde eine Nachricht zum Zurücksetzen des Passworts die hinterlegte E-Mail-Adresse gesendet. Wenn Sie diese E-Mail nicht erhalten, überprüfen Sie Ihre E-Mail-Adresse und/oder Ihren Kontonamen sowie Ihren Spam-/Junk-Ordner oder bitten Sie Ihre lokale Administration um Hilfe.", + "If this account exists, a password reset message has been sent to its email address. If you do not receive it, verify your email address and/or account name, check your spam/junk folders or ask your local administration for help." : "Sofern dieses Konto existiert, wurde eine Nachricht zum Zurücksetzen des Passworts an die hinterlegte E-Mail-Adresse gesendet. Wenn Sie diese E-Mail nicht erhalten, überprüfen Sie Ihre E-Mail-Adresse und/oder Ihren Kontonamen sowie Ihren Spam-/Junk-Ordner oder bitten Sie Ihre lokale Administration um Hilfe.", "Couldn't send reset email. Please contact your administrator." : "Die E-Mail zum Zurücksetzen konnte nicht versendet werden. Bitte kontaktieren Sie Ihre Administration.", "Password cannot be changed. Please contact your administrator." : "Passwort kann nicht geändert werden. Bitte kontaktieren Sie Ihren Administrator.", "Back to login" : "Zurück zur Anmeldung", @@ -268,7 +268,7 @@ "Authentication required" : "Legitimierung benötigt", "This action requires you to confirm your password" : "Dieser Vorgang benötigt eine Passwortbestätigung von Ihnen", "Confirm" : "Bestätigen", - "Failed to authenticate, try again" : "Legitimierung fehlgeschlagen, bitte erneut versuchen.", + "Failed to authenticate, try again" : "Authentifizierung fehlgeschlagen, bitte erneut versuchen.", "seconds ago" : "Gerade eben", "Connection to server lost" : "Verbindung zum Server verloren", "_Problem loading page, reloading in %n second_::_Problem loading page, reloading in %n seconds_" : ["Problem beim Laden der Seite, Seite wird in %n Sekunde nochmals geladen","Problem beim Laden der Seite. Seite wird in %n Sekunden erneut geladen"], @@ -308,7 +308,7 @@ "The profile does not exist." : "Das Profil existiert nicht.", "Back to %s" : "Zurück zu %s", "Page not found" : "Seite nicht gefunden", - "The page could not be found on the server or you may not be allowed to view it." : "Die Seite konnte auf dem Server nicht gefunden werden oder Sie sind nicht berechtigt sie anzeigen.", + "The page could not be found on the server or you may not be allowed to view it." : "Die Seite konnte auf dem Server nicht gefunden werden oder Sie sind nicht zum Anzeigen berechtigt.", "Too many requests" : "Zu viele Anfragen", "There were too many requests from your network. Retry later or contact your administrator if this is an error." : "Zu viele Anfragen aus Ihrem Netzwerk. Versuchen Sie es später erneut oder wenden Sie sich an Ihren Administrator, wenn dies ein Fehler sein sollte.", "Error" : "Fehler", diff --git a/core/openapi.json b/core/openapi.json index 6ffac746499..2371150caa1 100644 --- a/core/openapi.json +++ b/core/openapi.json @@ -1904,27 +1904,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2002,27 +1982,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2100,27 +2060,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -2191,27 +2131,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3809,27 +3729,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3839,27 +3739,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } @@ -3869,27 +3749,7 @@ "content": { "text/plain": { "schema": { - "type": "object", - "required": [ - "ocs" - ], - "properties": { - "ocs": { - "type": "object", - "required": [ - "meta", - "data" - ], - "properties": { - "meta": { - "$ref": "#/components/schemas/OCSMeta" - }, - "data": { - "type": "string" - } - } - } - } + "type": "string" } } } diff --git a/lib/l10n/ar.js b/lib/l10n/ar.js index 9843f5d2b0e..d274e3054cf 100644 --- a/lib/l10n/ar.js +++ b/lib/l10n/ar.js @@ -72,7 +72,7 @@ OC.L10N.register( "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "يبدو أن كائن %s يعمل على بيئة PHP 32-Bit وكذلك تم تكوين open_basedir في ملف php.ini. يؤدي ذلك إلى مشاكل مع الملفات التي يزيد حجمها عن 4 غيغابايت ولا يُنصح بذلك بشدة.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.", "Set an admin username." : "اعداد اسم مستخدم للمدير", - "Set an admin password." : "اعداد كلمة مرور للمدير", + "Set an admin password." : "تعيين كلمة مرور للمدير", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "يجب أن تقوم الواجهة الخلفية للمشاركة (Sharing backend) %s بتطبيق الواجهة OCP\\Share_Backend", "Sharing backend %s not found" : "لم يتم العثور على الواجهة الخلفية (Sharing backend) %s", "Sharing backend for %s not found" : "مشاركة الخلفية لـ %s غير موجود", diff --git a/lib/l10n/ar.json b/lib/l10n/ar.json index b1ef7c2cce7..a1b3cd0fa28 100644 --- a/lib/l10n/ar.json +++ b/lib/l10n/ar.json @@ -70,7 +70,7 @@ "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "يبدو أن كائن %s يعمل على بيئة PHP 32-Bit وكذلك تم تكوين open_basedir في ملف php.ini. يؤدي ذلك إلى مشاكل مع الملفات التي يزيد حجمها عن 4 غيغابايت ولا يُنصح بذلك بشدة.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.", "Set an admin username." : "اعداد اسم مستخدم للمدير", - "Set an admin password." : "اعداد كلمة مرور للمدير", + "Set an admin password." : "تعيين كلمة مرور للمدير", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "يجب أن تقوم الواجهة الخلفية للمشاركة (Sharing backend) %s بتطبيق الواجهة OCP\\Share_Backend", "Sharing backend %s not found" : "لم يتم العثور على الواجهة الخلفية (Sharing backend) %s", "Sharing backend for %s not found" : "مشاركة الخلفية لـ %s غير موجود", diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js index d750cf0002e..d9cdf4a1001 100644 --- a/lib/l10n/zh_CN.js +++ b/lib/l10n/zh_CN.js @@ -57,6 +57,7 @@ OC.L10N.register( "Avatar image is not square" : "头像图像不是正方形", "Files" : "文件", "View profile" : "查看个人资料", + "Local time: %s" : "当地时间:%s", "today" : "今天", "tomorrow" : "明天", "yesterday" : "昨天", diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json index c912cee2b76..cad9737dcf8 100644 --- a/lib/l10n/zh_CN.json +++ b/lib/l10n/zh_CN.json @@ -55,6 +55,7 @@ "Avatar image is not square" : "头像图像不是正方形", "Files" : "文件", "View profile" : "查看个人资料", + "Local time: %s" : "当地时间:%s", "today" : "今天", "tomorrow" : "明天", "yesterday" : "昨天", diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index ea60de137d2..978b5b0451c 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -87,17 +87,13 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil if (isset($params['validateWrites'])) { $this->validateWrites = (bool)$params['validateWrites']; } - //initialize cache with root directory in cache - if (!$this->is_dir('/')) { - $this->mkdir('/'); - } $this->logger = \OC::$server->getLogger(); } - public function mkdir($path) { + public function mkdir($path, bool $force = false) { $path = $this->normalizePath($path); - if ($this->file_exists($path)) { + if (!$force && $this->file_exists($path)) { $this->logger->warning("Tried to create an object store folder that already exists: $path"); return false; } @@ -246,6 +242,13 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil if ($cacheEntry instanceof CacheEntry) { return $cacheEntry->getData(); } else { + if ($path === '') { + $this->mkdir('', true); + $cacheEntry = $this->getCache()->get($path); + if ($cacheEntry instanceof CacheEntry) { + return $cacheEntry->getData(); + } + } return false; } } @@ -357,6 +360,12 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil case 'wb': case 'w+': case 'wb+': + $dirName = dirname($path); + $parentExists = $this->is_dir($dirName); + if (!$parentExists) { + return false; + } + $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext); $handle = fopen($tmpFile, $mode); return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) { @@ -469,6 +478,9 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil public function file_put_contents($path, $data) { $handle = $this->fopen($path, 'w+'); + if (!$handle) { + return false; + } $result = fwrite($handle, $data); fclose($handle); return $result; diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php index b6f96fffba4..bde25a3385a 100644 --- a/lib/private/Memcache/Redis.php +++ b/lib/private/Memcache/Redis.php @@ -32,6 +32,22 @@ namespace OC\Memcache; use OCP\IMemcacheTTL; class Redis extends Cache implements IMemcacheTTL { + /** name => [script, sha1] */ + public const LUA_SCRIPTS = [ + 'dec' => [ + 'if redis.call("exists", KEYS[1]) == 1 then return redis.call("decrby", KEYS[1], ARGV[1]) else return "NEX" end', + '720b40cb66cef1579f2ef16ec69b3da8c85510e9', + ], + 'cas' => [ + 'if redis.call("get", KEYS[1]) == ARGV[1] then redis.call("set", KEYS[1], ARGV[2]) return 1 else return 0 end', + '94eac401502554c02b811e3199baddde62d976d4', + ], + 'cad' => [ + 'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end', + 'cf0e94b2e9ffc7e04395cf88f7583fc309985910', + ], + ]; + /** * @var \Redis|\RedisCluster $cache */ @@ -54,18 +70,19 @@ class Redis extends Cache implements IMemcacheTTL { public function get($key) { $result = $this->getCache()->get($this->getPrefix() . $key); - if ($result === false && !$this->getCache()->exists($this->getPrefix() . $key)) { + if ($result === false) { return null; - } else { - return json_decode($result, true); } + + return self::decodeValue($result); } public function set($key, $value, $ttl = 0) { + $value = self::encodeValue($value); if ($ttl > 0) { - return $this->getCache()->setex($this->getPrefix() . $key, $ttl, json_encode($value)); + return $this->getCache()->setex($this->getPrefix() . $key, $ttl, $value); } else { - return $this->getCache()->set($this->getPrefix() . $key, json_encode($value)); + return $this->getCache()->set($this->getPrefix() . $key, $value); } } @@ -82,6 +99,7 @@ class Redis extends Cache implements IMemcacheTTL { } public function clear($prefix = '') { + // TODO: this is slow and would fail with Redis cluster $prefix = $this->getPrefix() . $prefix . '*'; $keys = $this->getCache()->keys($prefix); $deleted = $this->getCache()->del($keys); @@ -98,17 +116,14 @@ class Redis extends Cache implements IMemcacheTTL { * @return bool */ public function add($key, $value, $ttl = 0) { - // don't encode ints for inc/dec - if (!is_int($value)) { - $value = json_encode($value); - } + $value = self::encodeValue($value); $args = ['nx']; if ($ttl !== 0 && is_int($ttl)) { $args['ex'] = $ttl; } - return $this->getCache()->set($this->getPrefix() . $key, (string)$value, $args); + return $this->getCache()->set($this->getPrefix() . $key, $value, $args); } /** @@ -130,10 +145,8 @@ class Redis extends Cache implements IMemcacheTTL { * @return int | bool */ public function dec($key, $step = 1) { - if (!$this->hasKey($key)) { - return false; - } - return $this->getCache()->decrBy($this->getPrefix() . $key, $step); + $res = $this->evalLua('dec', [$key], [$step]); + return ($res === 'NEX') ? false : $res; } /** @@ -145,18 +158,10 @@ class Redis extends Cache implements IMemcacheTTL { * @return bool */ public function cas($key, $old, $new) { - if (!is_int($new)) { - $new = json_encode($new); - } - $this->getCache()->watch($this->getPrefix() . $key); - if ($this->get($key) === $old) { - $result = $this->getCache()->multi() - ->set($this->getPrefix() . $key, $new) - ->exec(); - return $result !== false; - } - $this->getCache()->unwatch(); - return false; + $old = self::encodeValue($old); + $new = self::encodeValue($new); + + return $this->evalLua('cas', [$key], [$old, $new]) > 0; } /** @@ -167,15 +172,9 @@ class Redis extends Cache implements IMemcacheTTL { * @return bool */ public function cad($key, $old) { - $this->getCache()->watch($this->getPrefix() . $key); - if ($this->get($key) === $old) { - $result = $this->getCache()->multi() - ->unlink($this->getPrefix() . $key) - ->exec(); - return $result !== false; - } - $this->getCache()->unwatch(); - return false; + $old = self::encodeValue($old); + + return $this->evalLua('cad', [$key], [$old]) > 0; } public function setTTL($key, $ttl) { @@ -185,4 +184,25 @@ class Redis extends Cache implements IMemcacheTTL { public static function isAvailable(): bool { return \OC::$server->getGetRedisFactory()->isAvailable(); } + + protected function evalLua(string $scriptName, array $keys, array $args) { + $keys = array_map(fn ($key) => $this->getPrefix() . $key, $keys); + $args = array_merge($keys, $args); + $script = self::LUA_SCRIPTS[$scriptName]; + + $result = $this->getCache()->evalSha($script[1], $args, count($keys)); + if (false === $result) { + $result = $this->getCache()->eval($script[0], $args, count($keys)); + } + + return $result; + } + + protected static function encodeValue(mixed $value): string { + return is_int($value) ? (string) $value : json_encode($value); + } + + protected static function decodeValue(string $value): mixed { + return is_numeric($value) ? (int) $value : json_decode($value, true); + } } diff --git a/lib/public/Mail/IMessage.php b/lib/public/Mail/IMessage.php index b3cc86839f1..08545138d37 100644 --- a/lib/public/Mail/IMessage.php +++ b/lib/public/Mail/IMessage.php @@ -47,7 +47,7 @@ interface IMessage { * @param string|null $contentType MIME Content-Type (e.g. text/plain or text/calendar) * * @return IMessage - * @since 26.0.0 + * @since 27.0.0 */ public function attachInline(string $body, string $name, string $contentType = null): IMessage; diff --git a/package-lock.json b/package-lock.json index 7173383d87e..1a987da89af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22118,9 +22118,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", @@ -42980,9 +42980,9 @@ } }, "socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "requires": { "@socket.io/component-emitter": "~3.1.0", diff --git a/tests/lib/Memcache/RedisTest.php b/tests/lib/Memcache/RedisTest.php index 276dbf3a550..b94b69a5e6a 100644 --- a/tests/lib/Memcache/RedisTest.php +++ b/tests/lib/Memcache/RedisTest.php @@ -56,4 +56,10 @@ class RedisTest extends Cache { parent::setUp(); $this->instance = new \OC\Memcache\Redis($this->getUniqueID()); } + + public function testScriptHashes() { + foreach (\OC\Memcache\Redis::LUA_SCRIPTS as $script) { + $this->assertEquals(sha1($script[0]), $script[1]); + } + } } diff --git a/version.php b/version.php index 97094fdf951..0256730054d 100644 --- a/version.php +++ b/version.php @@ -30,10 +30,10 @@ // between betas, final and RCs. This is _not_ the public version number. Reset minor/patch level // when updating major/minor version number. -$OC_Version = [27, 0, 0, 5]; +$OC_Version = [27, 0, 0, 6]; // The human-readable string -$OC_VersionString = '27.0.0 RC2'; +$OC_VersionString = '27.0.0 RC3'; $OC_VersionCanBeUpgradedFrom = [ 'nextcloud' => [ |