Compare commits

...
10 Commits
60 changed files with 1283 additions and 383 deletions

No files matched your search

@@ -87,17 +87,6 @@ jobs:
echo "✅ Successfully merged '$BETA_BRANCH' into '$STABLE_BRANCH'."
# - name: Delete beta branch after successful merge
# run: |
# VERSION="${{ github.event.inputs.version }}"
# BETA_BRANCH="beta/v$VERSION"
#
# # Delete beta branch locally and remotely
# git branch -d "$BETA_BRANCH"
# git push origin --delete "$BETA_BRANCH"
#
# echo "✅ Successfully deleted '$BETA_BRANCH'."
- name: Create Pull Request to Main
uses: peter-evans/create-pull-request@v6
with:
@@ -86,14 +86,3 @@ jobs:
git push origin "$BETA_BRANCH"
echo "✅ Successfully merged '$DEV_BRANCH' into '$BETA_BRANCH'."
# - name: Delete dev branch after successful merge
# run: |
# VERSION="${{ github.event.inputs.version }}"
# DEV_BRANCH="dev/v$VERSION"
#
# # Delete dev branch locally and remotely
# git branch -d "$DEV_BRANCH"
# git push origin --delete "$DEV_BRANCH"
#
# echo "✅ Successfully deleted '$DEV_BRANCH'."
+2 -2
View File
@@ -59,8 +59,8 @@ jobs:
target_commitish: ${{ github.sha }}
token: ${{ secrets.PAT }}
tag_name: ${{ steps.extract_branch.outputs.tag_name }}
prerelease: false # change this to false when stable gets released
make_latest: true # change this to false when stable gets released
prerelease: false
make_latest: false
draft: false
generate_release_notes: true
name: ${{ steps.extract_branch.outputs.tag_name }}
+2 -1
View File
@@ -10,7 +10,7 @@ permissions:
jobs:
test_playwright:
name: Test Playwright
name: Test Playwright - regular
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -60,6 +60,7 @@ jobs:
token: ${{ secrets.PAT }}
tag_name: ${{ steps.extract_branch.outputs.tag_name }}
prerelease: false
make_latest: true
draft: false
generate_release_notes: true
name: ${{ steps.extract_branch.outputs.tag_name }}
+16
View File
@@ -2,6 +2,22 @@
All notable changes to this project will be documented in this file. For commit guidelines, please refer to [Standard Version](https://github.com/conventional-changelog/standard-version).
## v1.0.0
**Notes**:
- Enhanced onlyoffice debugger with more wholistic backend logs
- Updated info prompt styling
- share qr code links to externalUrl for entire share if exists #1329
**BugFixes**:
- cookie host is set using x-Forwarded-Host to better support reverse proxies.
- HEIC conversion not working #1460
- 'Prevent user changing their password' also prevents admins changing the users password. #1365
- OnlyOffice write problem #1397 #1068
- Conditionals starting with a . seem to not work. #1455
- Last modified in file info is empty #1443
- Share links: 'Default View Mode' does not apply to subfolders. #1463
## v0.8.11-beta
**New Features**:
+1 -1
View File
@@ -14,4 +14,4 @@ RUN mkdir -p ./http/dist
COPY [ "./backend/http/embed/", "./http/dist/"]
# Run tests
#RUN ./filebrowser & sleep 2 && cd ../frontend && npx playwright test
RUN ./filebrowser & sleep 2 && cd ../frontend && npx playwright test
+8 -3
View File
@@ -26,10 +26,17 @@ server:
viewable: true
- fileStartsWith: "startsWith"
- folderEndsWith: "Folder"
- folderNames: 'folderNames'
- fileNames: 'fileNames'
- folderName: 'folderName'
- fileName: 'fileName'
- folderName: '.hiddenDir'
- fileName: '.hidden'
auth:
methods:
noauth: true
frontend:
name: "Graham's Filebrowser"
disableDefaultLinks: true
@@ -37,11 +44,9 @@ frontend:
- text: "A playwright test"
url: "https://playwright.dev/"
title: "Playwright"
userDefaults:
permissions:
realtime: true
userDefaults:
showHidden: true
preview:
image: true
popup: true
-7
View File
@@ -15,9 +15,6 @@ func validateAccessRules() {
if store.Access == nil {
return
}
logger.Info("Validating and migrating access rules to new format...")
// Get all sources
for sourcePath := range settings.Config.Server.SourceMap {
// Clear cache before migration to ensure we get fresh data
@@ -50,8 +47,6 @@ func validateAccessRules() {
// Create the new path with trailing slash
newPath := oldPath + "/"
logger.Debugf("Migrating access rule from '%s' to '%s'", oldPath, newPath)
// Migrate the rule to the new path
if err := migrateAccessRule(sourcePath, oldPath, newPath, rule); err != nil {
logger.Errorf("Failed to migrate rule from %s to %s: %v", oldPath, newPath, err)
@@ -74,8 +69,6 @@ func validateAccessRules() {
logger.Infof("Migrated %d access rules for source %s", migratedCount, sourcePath)
}
}
logger.Info("Access rules validation completed")
}
// migrateAccessRule creates a new access rule with the new path format
+19 -1
View File
@@ -99,7 +99,13 @@ func setupFrontend(generate bool) {
}
Config.Frontend.Styling.LightBackground = FallbackColor(Config.Frontend.Styling.LightBackground, "#f5f5f5")
Config.Frontend.Styling.DarkBackground = FallbackColor(Config.Frontend.Styling.DarkBackground, "#141D24")
Config.Frontend.Styling.CustomCSSRaw = readCustomCSS(Config.Frontend.Styling.CustomCSS)
var err error
if Config.Frontend.Styling.CustomCSS != "" {
Config.Frontend.Styling.CustomCSSRaw, err = readCustomCSS(Config.Frontend.Styling.CustomCSS)
if err != nil {
logger.Warning(err.Error())
}
}
Config.Frontend.Styling.CustomThemeOptions = map[string]CustomTheme{}
if Config.Frontend.Styling.CustomThemes == nil {
Config.Frontend.Styling.CustomThemes = map[string]CustomTheme{}
@@ -770,6 +776,18 @@ func setConditionals(config *Source) {
if rule.IncludeRootItem != "" {
resolved.IncludeRootItems[rule.IncludeRootItem] = struct{}{}
}
if rule.FileNames != "" {
resolved.FileNames[rule.FileNames] = rule
}
if rule.FolderNames != "" {
resolved.FolderNames[rule.FolderNames] = rule
}
if rule.FileName != "" {
resolved.FileNames[rule.FileName] = rule
}
if rule.FolderName != "" {
resolved.FolderNames[rule.FolderName] = rule
}
}
config.Config.ResolvedConditionals = resolved
}
+17 -11
View File
@@ -1,6 +1,8 @@
package settings
import (
"errors"
"fmt"
"os"
"regexp"
"strings"
@@ -83,7 +85,13 @@ func addCustomTheme(name, description, cssFilePath string) {
// Load CSS content for runtime use (frontend consumption)
cssContent := ""
if cssFilePath != "" {
cssContent = readCustomCSS(cssFilePath)
var err error
cssContent, err = readCustomCSS(cssFilePath)
if err != nil {
logger.Warning(err.Error())
return
}
}
Config.Frontend.Styling.CustomThemeOptions[name] = CustomTheme{
Description: description,
@@ -92,22 +100,20 @@ func addCustomTheme(name, description, cssFilePath string) {
}
}
func readCustomCSS(path string) string {
func readCustomCSS(path string) (string, error) {
if path == "" {
return ""
return "", errors.New("path is empty")
}
content, err := os.ReadFile(path)
if err != nil {
// Only log if the file exists but cannot be read (e.g., permission error)
if !os.IsNotExist(err) {
logger.Warningf("Could not read custom CSS file %s: %v", path, err)
return ""
}
return "", fmt.Errorf("could not read custom CSS file: %v", err)
}
if len(content) > 128*1024 {
logger.Warningf("Custom CSS file %s is too large (%d bytes), ignoring", path, len(content))
return ""
return "", fmt.Errorf("custom CSS file is too large (%d bytes)", len(content))
}
if len(content) == 0 {
return "", fmt.Errorf("custom CSS file is empty: %s", path)
}
logger.Debugf("Loaded custom CSS from: %s (%d bytes)", path, len(content))
return string(content)
return string(content), nil
}
+1 -1
View File
@@ -87,7 +87,7 @@ func (st usersBackend) Update(user *users.User, actorIsAdmin bool, fields ...str
if !slices.Contains(fields, "Password") {
user.Password = existingUser.Password
} else {
if existingUser.LockPassword {
if existingUser.LockPassword && !actorIsAdmin {
return fmt.Errorf("password cannot be changed when lock password is enabled")
}
}
+12 -2
View File
@@ -144,10 +144,15 @@ func logoutHandler(w http.ResponseWriter, r *http.Request, d *requestContext) (i
defer auth.RevokeAPIKey(d.token)
// Clear the authentication cookie by setting it to expire in the past
// Get the correct domain for cookie - prefer X-Forwarded-Host from reverse proxy
host := r.Header.Get("X-Forwarded-Host")
if host == "" {
host = r.Host
}
cookie := &http.Cookie{
Name: "filebrowser_quantum_jwt",
Value: "",
Domain: strings.Split(r.Host, ":")[0],
Domain: strings.Split(host, ":")[0],
Path: "/",
SameSite: http.SameSiteLaxMode,
Expires: time.Unix(0, 0), // Expire immediately
@@ -262,10 +267,15 @@ func printToken(w http.ResponseWriter, r *http.Request, user *users.User) (int,
expiresTime := time.Now().Add(expires).Add(time.Minute * 30)
// Set the authentication token as an HTTP cookie
// Get the correct domain for cookie - prefer X-Forwarded-Host from reverse proxy
host := r.Header.Get("X-Forwarded-Host")
if host == "" {
host = r.Host
}
cookie := &http.Cookie{
Name: "filebrowser_quantum_jwt",
Value: signed.Key,
Domain: strings.Split(r.Host, ":")[0], // Set domain to the host without port
Domain: strings.Split(host, ":")[0], // Set domain to the host without port
Path: "/",
SameSite: http.SameSiteLaxMode,
Expires: expiresTime,
+6 -1
View File
@@ -346,10 +346,15 @@ func loginWithOidcUser(w http.ResponseWriter, r *http.Request, username string,
expiresTime := time.Now().Add(expires).Add(time.Minute * 30)
// Set the authentication token as an HTTP cookie
// Get the correct domain for cookie - prefer X-Forwarded-Host from reverse proxy
host := r.Header.Get("X-Forwarded-Host")
if host == "" {
host = r.Host
}
cookie := &http.Cookie{
Name: "filebrowser_quantum_jwt",
Value: signed.Key,
Domain: strings.Split(r.Host, ":")[0], // Set domain to the host without port
Domain: strings.Split(host, ":")[0], // Set domain to the host without port
Path: "/",
SameSite: http.SameSiteLaxMode, // Lax mode allows cookie on navigation from OIDC provider
Expires: expiresTime,
+24 -32
View File
@@ -175,8 +175,8 @@ func onlyofficeClientConfigGetHandler(w http.ResponseWriter, r *http.Request, d
)
storeOnlyOfficeLogContext(documentId, logContext)
// Send initial log event
sendOnlyOfficeLogEvent(logContext, "INFO", "config", fmt.Sprintf("OnlyOffice session started for document: %s", d.fileInfo.Name))
// Send initial log event with detailed path information
sendOnlyOfficeLogEvent(logContext, "INFO", "config", fmt.Sprintf("OnlyOffice session started for document: %s ", path))
// Build download URL that OnlyOffice server will use
downloadURL := buildOnlyOfficeDownloadURL(source, providedPath, d.fileInfo.Hash, d.token)
@@ -440,8 +440,8 @@ func processOnlyOfficeCallback(w http.ResponseWriter, r *http.Request, d *reques
} else {
// Verify user has modify permissions
if !d.user.Permissions.Modify {
logger.Errorf("OnlyOffice callback: user %s lacks modify permissions for source=%s, path=%s",
d.user.Username, source, path)
logger.Errorf("OnlyOffice callback: user %s lacks modify permissions for path=%s",
d.user.Username, path)
return returnOnlyOfficeError(w, r, 403, "user lacks modify permissions")
}
}
@@ -460,60 +460,52 @@ func processOnlyOfficeCallback(w http.ResponseWriter, r *http.Request, d *reques
return returnOnlyOfficeError(w, r, 500, "failed to download document from OnlyOffice server")
}
// Resolve file path for writing (same logic as in config handler)
resolvedPath := path
if d.fileInfo.Hash == "" {
// Regular user request - need to resolve scope
userScope, scopeErr := settings.GetScopeFromSourceName(d.user.Scopes, source)
if scopeErr != nil {
logger.Errorf("OnlyOffice callback: source %s not available for user %s: %v",
source, d.user.Username, scopeErr)
return returnOnlyOfficeError(w, r, 403, "source not available")
}
resolvedPath = utils.JoinPathAsUnix(userScope, path)
}
logger.Debugf("OnlyOffice callback: saving document to path=%s",
path)
logger.Debugf("OnlyOffice callback: saving document to path=%s, source=%s, user=%s",
resolvedPath, source, d.user.Username)
// Send detailed log event for file saving with path information
if logContext := getOnlyOfficeLogContext(data.Key); logContext != nil {
sendOnlyOfficeLogEvent(logContext, "INFO", "callback", fmt.Sprintf("Saving document to path: %s", path))
}
// CRITICAL: Validate that the original file still exists before saving
// This prevents creating duplicate files if the original was renamed/moved
_, err = files.FileInfoFaster(utils.FileOptions{
Source: source,
Path: resolvedPath,
Path: path,
}, nil)
if err != nil {
logger.Errorf("OnlyOffice callback: original file no longer exists at path=%s, source=%s: %v",
resolvedPath, source, err)
logger.Errorf("OnlyOffice callback: original file no longer exists at path=%s: %v",
path, err)
// Send error log event
// Send error log event with path information
if logContext := getOnlyOfficeLogContext(data.Key); logContext != nil {
sendOnlyOfficeLogEvent(logContext, "ERROR", "callback",
fmt.Sprintf("Original file no longer exists: %v -- was it renamed or moved?", err))
fmt.Sprintf("Original file no longer exists at path: %s - %v -- was it renamed or moved?", path, err))
}
return returnOnlyOfficeError(w, r, 404, "original file no longer exists - it may have been renamed or moved")
}
writeErr := files.WriteFile(source, resolvedPath, doc.Body)
writeErr := files.WriteFile(source, path, doc.Body)
if writeErr != nil {
logger.Errorf("OnlyOffice callback: failed to write updated document to path=%s, source=%s: %v",
resolvedPath, source, writeErr)
logger.Errorf("OnlyOffice callback: failed to write updated document to path=%s: %v",
path, writeErr)
// Send error log event
// Send error log event with path information
if logContext := getOnlyOfficeLogContext(data.Key); logContext != nil {
sendOnlyOfficeLogEvent(logContext, "ERROR", "callback", fmt.Sprintf("Failed to save document: %v", writeErr))
sendOnlyOfficeLogEvent(logContext, "ERROR", "callback", fmt.Sprintf("Failed to save document to path: %s - %v", path, writeErr))
}
return returnOnlyOfficeError(w, r, 500, "failed to save document")
}
logger.Infof("OnlyOffice callback: successfully saved document to path=%s, source=%s",
resolvedPath, source)
logger.Infof("OnlyOffice callback: successfully saved document to path=%s",
path)
// Send success log event
// Send success log event with detailed path information
if logContext := getOnlyOfficeLogContext(data.Key); logContext != nil {
sendOnlyOfficeLogEvent(logContext, "INFO", "callback", "Document saved successfully")
sendOnlyOfficeLogEvent(logContext, "INFO", "callback", fmt.Sprintf("Document saved successfully to path: %s", path))
}
}
+69
View File
@@ -19,6 +19,7 @@ import (
"github.com/gtsteffaniak/filebrowser/backend/common/settings"
"github.com/gtsteffaniak/filebrowser/backend/common/utils"
"github.com/gtsteffaniak/filebrowser/backend/indexing"
"github.com/gtsteffaniak/filebrowser/backend/indexing/iteminfo"
"github.com/gtsteffaniak/go-logger/logger"
"golang.org/x/time/rate"
)
@@ -254,9 +255,31 @@ func rawFilesHandler(w http.ResponseWriter, r *http.Request, d *requestContext,
var err error
var userscope string
fileName := filepath.Base(firstFilePath)
// Check if this is an OnlyOffice file early for error logging
isOnlyOffice := isOnlyOfficeCompatibleFile(fileName) && config.Integrations.OnlyOffice.Url != ""
var documentId string
var logContext *OnlyOfficeLogContext
if d.share == nil {
userscope, err = settings.GetScopeFromSourceName(d.user.Scopes, firstFileSource)
if err != nil {
// Send OnlyOffice error log if this was an OnlyOffice file
if isOnlyOffice {
// Try to get document ID for error logging
idx := indexing.GetIndex(firstFileSource)
if idx != nil {
tempPath := utils.JoinPathAsUnix(userscope, firstFilePath)
if realPath, _, realErr := idx.GetRealPath(tempPath); realErr == nil {
if docId, _ := getOnlyOfficeId(realPath); docId != "" {
if ctx := getOnlyOfficeLogContext(docId); ctx != nil {
sendOnlyOfficeLogEvent(ctx, "ERROR", "download",
fmt.Sprintf("OnlyOffice download failed - source not available: %s - %v", firstFilePath, err))
}
}
}
}
}
return http.StatusForbidden, err
}
firstFilePath = utils.JoinPathAsUnix(userscope, firstFilePath)
@@ -264,10 +287,24 @@ func rawFilesHandler(w http.ResponseWriter, r *http.Request, d *requestContext,
// For shares, the path is already correctly resolved by publicRawHandler
idx := indexing.GetIndex(firstFileSource)
if idx == nil {
// Send OnlyOffice error log if this was an OnlyOffice file
if isOnlyOffice {
sendOnlyOfficeLogEvent(logContext, "ERROR", "download",
fmt.Sprintf("OnlyOffice download failed - source index not available: %s", firstFileSource))
}
return http.StatusInternalServerError, fmt.Errorf("source %s is not available", firstFileSource)
}
realPath, isDir, err := idx.GetRealPath(firstFilePath)
if err != nil {
// Send OnlyOffice error log if this was an OnlyOffice file
if isOnlyOffice {
if docId, _ := getOnlyOfficeId(realPath); docId != "" {
if ctx := getOnlyOfficeLogContext(docId); ctx != nil {
sendOnlyOfficeLogEvent(ctx, "ERROR", "download",
fmt.Sprintf("OnlyOffice download failed - could not resolve path: %s - %v", firstFilePath, err))
}
}
}
return http.StatusInternalServerError, err
}
// Compute estimated download size
@@ -277,8 +314,21 @@ func rawFilesHandler(w http.ResponseWriter, r *http.Request, d *requestContext,
}
// ** Single file download with Content-Length **
if len(fileList) == 1 && !isDir {
// Get document ID and log context for OnlyOffice downloads
if isOnlyOffice {
documentId, _ = getOnlyOfficeId(realPath)
if documentId != "" {
logContext = getOnlyOfficeLogContext(documentId)
}
}
fd, err2 := os.Open(realPath)
if err2 != nil {
// Send OnlyOffice error log if this was an OnlyOffice download
if isOnlyOffice && logContext != nil {
sendOnlyOfficeLogEvent(logContext, "ERROR", "download",
fmt.Sprintf("OnlyOffice download failed - could not open file: %s - %v", firstFilePath, err2))
}
return http.StatusInternalServerError, err2
}
defer fd.Close()
@@ -286,9 +336,23 @@ func rawFilesHandler(w http.ResponseWriter, r *http.Request, d *requestContext,
// Get file size
fileInfo, err2 := fd.Stat()
if err2 != nil {
// Send OnlyOffice error log if this was an OnlyOffice download
if isOnlyOffice && logContext != nil {
sendOnlyOfficeLogEvent(logContext, "ERROR", "download",
fmt.Sprintf("OnlyOffice download failed - could not get file info: %s - %v", firstFilePath, err2))
}
return http.StatusInternalServerError, err2
}
// Send success log for OnlyOffice downloads
if isOnlyOffice && logContext != nil {
logger.Infof("OnlyOffice Server is downloading file: %s (documentId: %s)",
firstFilePath, documentId)
sendOnlyOfficeLogEvent(logContext, "INFO", "download",
fmt.Sprintf("OnlyOffice Server downloading file: %s", firstFilePath))
}
// Set headers
setContentDisposition(w, r, fileName)
w.Header().Set("Cache-Control", "private")
@@ -478,3 +542,8 @@ func createTarGz(d *requestContext, tmpDirPath string, filenames ...string) erro
return nil
}
// isOnlyOfficeCompatibleFile checks if a file extension is supported by OnlyOffice
func isOnlyOfficeCompatibleFile(fileName string) bool {
return iteminfo.IsOnlyOffice(fileName)
}
+7 -2
View File
@@ -97,7 +97,7 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
shareProps["disableFileViewer"] = d.share.DisableFileViewer
shareProps["disableShareCard"] = d.share.DisableShareCard
shareProps["disableSidebar"] = d.share.DisableSidebar
shareProps["isPasswordProtected"] = d.share.PasswordHash != ""
shareProps["isPasswordProtected"] = d.share.HasPassword()
shareProps["downloadURL"] = getDownloadURL(r, d.share.Hash)
shareProps["enforceDarkLightMode"] = d.share.EnforceDarkLightMode
shareProps["viewMode"] = d.share.ViewMode
@@ -119,7 +119,6 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
shareProps["hideNavButtons"] = d.share.HideNavButtons
// Additional computed properties from extended.go
shareProps["hasPassword"] = d.share.HasPassword()
shareProps["isPermanent"] = d.share.IsPermanent()
shareProps["fileExtension"] = d.share.GetFileExtension()
shareProps["fileName"] = d.share.GetFileName()
@@ -136,6 +135,12 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *requestCont
if d.share.Title != "" {
data["title"] = d.share.Title
}
if d.share.ShareTheme != "" {
theme, ok := config.Frontend.Styling.CustomThemeOptions[d.share.ShareTheme]
if ok {
userSelectedTheme = theme.CssRaw
}
}
}
// base url could be different for routes behind proxy
+2
View File
@@ -52,6 +52,8 @@ var ResizableImageTypes = map[string]bool{
".png": true,
".gif": true,
".bmp": true,
".heic": true,
".heif": true,
".other": false,
}
+2 -1
View File
@@ -208,6 +208,7 @@ func GeneratePreviewWithMD5(ctx context.Context, file iteminfo.ExtendedFileInfo,
hasher := md5.New()
_, _ = hasher.Write([]byte(CacheKey(fileMD5, previewSize, seekPercentage)))
hash := hex.EncodeToString(hasher.Sum(nil))
convertHEIC := strings.HasPrefix(file.Type, "image/heic") && settings.Config.Integrations.Media.Convert.ImagePreview[settings.HEICImagePreview]
// Generate an image from office document
if iteminfo.HasDocConvertableExtension(file.Name, file.Type) {
tempFilePath := filepath.Join(settings.Config.Server.CacheDir, "thumbnails", "docs", hash) + ".txt"
@@ -220,7 +221,7 @@ func GeneratePreviewWithMD5(ctx context.Context, file iteminfo.ExtendedFileInfo,
if err != nil {
return nil, fmt.Errorf("failed to create image for office file: %w", err)
}
} else if strings.HasPrefix(file.Type, "image/heic") {
} else if convertHEIC {
// HEIC files need FFmpeg conversion to JPEG with proper size/quality handling
imageBytes, err = service.convertHEICToJPEGWithFFmpeg(ctx, file.RealPath, previewSize)
if err != nil {
@@ -27,13 +27,13 @@
</div>
<div v-if="!shareInfo.disableDownload" class="share__box__element share__box__center">
<button class="button button--flat clickable" @click="goToLink()"> {{ $t("buttons.download") }} </button>
<button class="button button--flat clickable" @click="goToDownload()"> {{ $t("buttons.download") }} </button>
</div>
</div>
</div>
<div v-if="req.type" class="share__box__element share__box__center">
<qrcode-vue class="qrcode" :value="getLink(false)" size="200" level="M"></qrcode-vue>
<qrcode-vue class="qrcode" :value="getShareLink()" size="200" level="M"></qrcode-vue>
</div>
</div>
</div>
@@ -114,16 +114,19 @@ export default {
},
},
methods: {
goToLink() {
window.open(this.getLink(false), "_blank");
},
getLink(inline = false) {
return publicApi.getDownloadURL({
goToDownload() {
const downloadLink = publicApi.getDownloadURL({
path: "/",
hash: state.share.hash,
token: state.share.token,
inline: inline,
inline: false,
}, [state.req.path]);
window.open(downloadLink, "_blank");
},
getShareLink() {
return publicApi.getShareURL({
hash: state.share.hash,
});
},
},
};
+4 -4
View File
@@ -14,7 +14,7 @@
<div class="shortcuts-grid">
<!-- Function Keys Section -->
<div class="shortcut-section">
<h3 class="section-title">Function Keys</h3> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<h3 class="section-title">{{ $t("help.functionKeys") }}</h3>
<div class="shortcut-item">
<kbd>F1</kbd> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<span>{{ $t("help.f1") }}</span>
@@ -39,7 +39,7 @@
<!-- Mouse Actions Section -->
<div class="shortcut-section">
<h3 class="section-title">Mouse Actions</h3> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<h3 class="section-title">{{ $t("help.mouseActions") }}</h3>
<div class="shortcut-item">
<kbd>Click</kbd> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<span>{{ $t("help.click") }}</span>
@@ -52,7 +52,7 @@
<!-- File Operations Section -->
<div class="shortcut-section">
<h3 class="section-title">File Operations</h3> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<h3 class="section-title">{{ $t("help.fileOperations") }}</h3>
<div class="shortcut-item">
<kbd>CTRL + C</kbd> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<span>{{ $t("help.ctrl.c") }}</span>
@@ -73,7 +73,7 @@
<!-- Navigation Section -->
<div class="shortcut-section">
<h3 class="section-title">Navigation</h3> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<h3 class="section-title">{{ $t("help.navigation") }}</h3>
<div class="shortcut-item">
<kbd>CTRL + B</kbd> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<span>{{ $t("help.ctrl.b") }}</span>
+345 -68
View File
@@ -3,56 +3,123 @@
<h2>{{ $t("prompts.fileInfo") }}</h2>
</div>
<div class="card-content">
<p v-if="selected.length > 1">
<div class="card-content info-content">
<p v-if="selected.length > 1" class="info-description">
{{ $t("prompts.filesSelected", { count: selected.length }) }}
</p>
<p class="break-word" v-if="selected.length < 2">
<strong>{{ $t("prompts.displayName") }}</strong> {{ name }}
</p>
<p v-if="!dir || selected.length > 1">
<strong>{{ $t("prompts.size") }}:</strong> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<span id="content_length"></span> {{ humanSize }}
</p>
<p v-if="!dir || selected.length > 1">
<strong>{{ $t('prompts.typeName') }}</strong>
<span id="content_length"></span> {{ type }}
</p>
<p v-if="selected.length < 2" :title="modTime">
<strong>{{ $t("prompts.lastModified", { suffix: ":" }) }}</strong>
<!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</p>
<div class="info-grid">
<!-- Basic Information Section -->
<div class="info-section">
<h3 class="section-title">{{ $t("prompts.basicInfo") }}</h3>
<div class="info-item">
<strong>{{ $t("prompts.displayName") }}</strong>
<span aria-label="info display name">{{ displayName }}</span>
</div>
<div class="info-item">
<strong>{{ $t("prompts.size") }}</strong>
<span aria-label="info size">{{ humanSize }}</span>
</div>
<div class="info-item">
<strong>{{ $t("prompts.typeName") }}</strong>
<span aria-label="info type">{{ type }}</span>
</div>
<div class="info-item" v-if="selected.length < 2 && humanTime">
<strong>{{ $t("prompts.lastModified") }}</strong>
<span aria-label="info last modified" :title="modTime">{{ humanTime }}</span>
</div>
<div class="info-item" v-if="selected.length < 2 && source">
<strong>{{ $t("prompts.source") }}</strong>
<span aria-label="info source">{{ source }}</span>
</div>
<div class="info-item" v-if="selected.length < 2 && filePath">
<strong>{{ $t("general.path") }}</strong>
<span aria-label="info path" class="break-word">{{ filePath }}</span>
</div>
<div class="info-item" v-if="hidden !== undefined">
<strong>{{ $t("prompts.hidden") }}</strong>
<span aria-label="info hidden">{{ hidden ? "✓" : "✗" }}</span> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</div>
<div class="info-item" v-if="hasPreview !== undefined">
<strong>{{ $t("prompts.hasPreview") }}</strong>
<span aria-label="info has preview">{{ hasPreview ? "✓" : "✗" }}</span> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</div>
</div>
<!-- Directory Information Section -->
<div class="info-section" v-if="dir && selected.length === 0">
<h3 class="section-title">{{ $t("prompts.directoryInfo") }}</h3>
<div class="info-item">
<strong>{{ $t("prompts.numberFiles") }}</strong>
<span>{{ req.numFiles }}</span>
</div>
<div class="info-item">
<strong>{{ $t("prompts.numberDirs") }}</strong>
<span>{{ req.numDirs }}</span>
</div>
</div>
<!-- Hash Generator Section -->
<div class="info-section" v-if="!dir">
<h3 class="section-title">{{ $t("prompts.checksums") }}</h3>
<div class="hash-generator">
<div class="hash-select">
<label for="hash-algo">{{ $t("prompts.hashAlgorithm") }}</label>
<div class="form-flex-group">
<select id="hash-algo" class="input form-form flat-right" v-model="selectedHashAlgo">
<option value="md5">MD5</option> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<option value="sha1">SHA1</option> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<option value="sha256">SHA256</option> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<option value="sha512">SHA512</option> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</select>
<button
type="button"
class="button form-button flat-left"
@click="generateHash"
:title="$t('prompts.generate')"
:aria-label="$t('prompts.generate')"
>
{{ $t("prompts.generate") }}
</button>
</div>
</div>
<template v-if="dir && selected.length === 0">
<p>
<strong>{{ $t("prompts.numberFiles", { suffix: ":" }) }}</strong> {{ req.numFiles }}
<!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</p>
<p>
<strong>{{ $t("prompts.numberDirs", { suffix: ":" }) }}</strong> {{ req.numDirs }}
<!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
</p>
</template>
<div class="hash-result">
<label for="hash-result">{{ $t("prompts.hashValue") }}</label>
<div class="form-flex-group">
<input
style="height: 100%"
id="hash-result"
class="input form-form flat-right"
type="text"
:value="hashResult"
readonly
:placeholder="$t('prompts.selectHashAlgorithm')"
/>
<button
class="button form-button flat-left"
@click="copyToClipboard"
:disabled="!hashResult"
:title="$t('buttons.copyToClipboard')"
:aria-label="$t('buttons.copyToClipboard')"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
<template v-if="!dir">
<p>
<strong>MD5: </strong> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<code><a @click="checksum($event, 'md5')">{{ $t("prompts.show") }}</a></code>
</p>
<p>
<strong>SHA1: </strong> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<code><a @click="checksum($event, 'sha1')">{{ $t("prompts.show") }}</a></code>
</p>
<p>
<strong>SHA256: </strong> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<code><a @click="checksum($event, 'sha256')">{{ $t("prompts.show") }}</a></code>
</p>
<p>
<strong>SHA512: </strong> <!-- eslint-disable-line @intlify/vue-i18n/no-raw-text -->
<code><a @click="checksum($event, 'sha512')">{{ $t("prompts.show") }}</a></code>
</p>
</template>
<!-- Additional Information Section -->
<div class="info-section" v-if="additionalInfo.length > 0">
<h3 class="section-title">{{ $t("prompts.additionalInfo") }}</h3>
<div class="info-item" v-for="info in additionalInfo" :key="info.key">
<strong>{{ info.label }}</strong>
<span>{{ info.value }}</span>
</div>
</div>
</div>
</div>
<div class="card-action">
@@ -66,10 +133,18 @@
import { getHumanReadableFilesize } from "@/utils/filesizes";
import { formatTimestamp } from "@/utils/moment";
import { filesApi } from "@/api";
import { state, getters, mutations } from "@/store"; // Import your custom store
import { state, getters, mutations } from "@/store";
import { notify } from "@/notify";
export default {
name: "info",
data() {
return {
selectedHashAlgo: "md5",
hashResult: "",
generatingHash: false,
};
},
computed: {
closeHovers() {
return mutations.closeHovers;
@@ -104,21 +179,31 @@ export default {
},
humanTime() {
if (state.isSearchActive) {
return "unknown";
return "";
}
if (getters.selectedCount() === 0) {
return formatTimestamp(state.req.modified, state.user.locale);
const modifiedDate = getters.selectedCount() === 0
? state.req.modified
: state.req.items[this.selected[0]]?.modified;
if (!modifiedDate) {
return "";
}
return formatTimestamp(
state.req.items[this.selected[0]].modified,
state.user.locale
);
return formatTimestamp(modifiedDate, state.user.locale);
},
modTime() {
if (state.isSearchActive) {
return "";
}
return new Date(Date.parse(state.req.modified)).toLocaleString();
const modifiedDate = getters.selectedCount() === 0
? state.req.modified
: state.req.items[this.selected[0]]?.modified;
if (!modifiedDate) {
return "";
}
return new Date(Date.parse(modifiedDate)).toLocaleString();
},
name() {
if (state.isSearchActive) {
@@ -136,6 +221,12 @@ export default {
? state.req.type
: state.req.items[this.selected[0]].type;
},
displayName() {
if (this.selected.length > 1) {
return this.$t("prompts.fileInfo");
}
return this.name;
},
dir() {
if (state.isSearchActive) {
return state.selected[0].type === "directory";
@@ -147,25 +238,211 @@ export default {
: state.req.items[this.selected[0]].type == "directory")
);
},
},
methods: {
async checksum(event, algo) {
event.preventDefault();
let link;
source() {
if (state.isSearchActive) {
const hash = await filesApi.checksum(state.selected[0].source, state.selected[0].path, algo);
event.target.innerHTML = hash;
return;
return state.selected[0].source;
}
if (getters.selectedCount()) {
link = state.req.items[this.selected[0]].path;
} else {
link = state.route.path;
const currentSource = state.sources.current;
if (!currentSource || currentSource === "") {
return "";
}
return currentSource;
},
filePath() {
if (state.isSearchActive) {
return state.selected[0].path;
}
if (getters.selectedCount() === 0) {
return state.route.path;
}
return state.req.items[this.selected[0]]?.path || "";
},
hidden() {
if (state.isSearchActive) {
return state.selected[0].hidden;
}
if (getters.selectedCount() === 0) {
return state.req.hidden;
}
return state.req.items[this.selected[0]]?.hidden;
},
hasPreview() {
if (state.isSearchActive) {
return state.selected[0].hasPreview;
}
if (getters.selectedCount() === 0) {
return state.req.hasPreview;
}
return state.req.items[this.selected[0]]?.hasPreview;
},
additionalInfo() {
const info = [];
// Add more info fields here if needed
if (state.req.token) {
info.push({ key: "token", label: this.$t("prompts.token"), value: state.req.token });
}
if (state.req.hash) {
info.push({ key: "hash", label: this.$t("general.hash"), value: state.req.hash });
}
if (state.req.onlyOfficeId) {
info.push({ key: "onlyOfficeId", label: this.$t("prompts.onlyOfficeId"), value: state.req.onlyOfficeId });
}
const hash = await filesApi.checksum(state.sources.current, link, algo);
event.target.innerHTML = hash;
return info;
},
},
methods: {
async generateHash() {
if (this.generatingHash) return;
this.hashResult = "";
this.generatingHash = true;
try {
let source, path;
if (state.isSearchActive) {
source = state.selected[0].source;
path = state.selected[0].path;
} else if (getters.selectedCount()) {
source = state.sources.current;
path = state.req.items[this.selected[0]].path;
} else {
source = state.sources.current;
path = state.route.path;
}
const hash = await filesApi.checksum(source, path, this.selectedHashAlgo);
this.hashResult = hash;
} catch (err) {
this.hashResult = this.$t("prompts.errorGeneratingHash");
notify.showError(err.message || "Error generating hash");
} finally {
this.generatingHash = false;
}
},
async copyToClipboard() {
if (!this.hashResult) return;
try {
await navigator.clipboard.writeText(this.hashResult);
notify.showSuccess(this.$t("prompts.hashCopied"));
} catch (err) {
// Fallback for older browsers
const textArea = document.createElement("textarea");
textArea.value = this.hashResult;
textArea.style.position = "fixed";
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand("copy");
notify.showSuccess(this.$t("prompts.hashCopied"));
} catch (e) {
notify.showError(this.$t("prompts.errorCopyingHash"));
}
document.body.removeChild(textArea);
}
},
},
};
</script>
<style scoped>
.info-content {
max-height: 70vh;
overflow-y: auto;
}
.info-description {
margin-bottom: 1.5em;
color: var(--textSecondary);
line-height: 1.5;
text-align: center;
}
.info-grid {
display: grid;
gap: 1.5em;
}
.info-section {
display: flex;
flex-direction: column;
gap: 0.5em;
}
.section-title {
font-size: 0.95em;
font-weight: 600;
color: var(--textPrimary);
margin: 0 0 0.75em 0;
padding-bottom: 0.5em;
border-bottom: 1px solid var(--divider);
}
.info-item {
display: flex;
align-items: flex-start;
gap: 0.75em;
padding: 0.5em;
border-radius: 4px;
transition: background-color 0.2s;
}
.info-item:hover {
background-color: var(--surfaceSecondary);
}
.info-item strong {
min-width: 120px;
font-weight: 600;
color: var(--textPrimary);
}
.info-item span {
flex: 1;
color: var(--textSecondary);
word-break: break-word;
}
.break-word {
word-break: break-word;
}
.hash-generator {
display: flex;
flex-direction: column;
gap: 1em;
}
.hash-select,
.hash-result {
display: flex;
flex-direction: column;
gap: 0.5em;
}
.hash-select label,
.hash-result label {
font-weight: 600;
font-size: 0.9em;
color: var(--textPrimary);
}
#hash-result {
font-family: monospace;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.info-grid {
grid-template-columns: 1fr;
}
.info-item strong {
min-width: 100px;
}
}
</style>
+1 -1
View File
@@ -162,7 +162,7 @@ export default {
if (getters.isShare()) {
return shareInfo.allowCreate
}
return state.user.permissions.create || state.user.permissions.share || state.user.permissions.admin;
return state.user?.permissions?.create || state.user?.permissions?.share || state.user?.permissions?.admin;
},
shareInfo: () => shareInfo,
disableQuickToggles: () => state.user?.disableQuickToggles,
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "التنزيل غير متاح."
},
"help": {
"functionKeys": "مفاتيح الوظائف",
"mouseActions": "إجراءات الفأرة",
"fileOperations": "عمليات الملفات",
"navigation": "التنقل",
"click": "حدد الملف أو المجلد",
"ctrl": {
"click": "حدد أكثر من ملف او مجلد",
@@ -226,7 +230,22 @@
"sourcePath": "المصدر:",
"destinationPath": "الوجهة",
"closeWithActiveUploadsMessage": "تحذير: لديك تحميلات نشطة وقد يؤدي إغلاق مطالبة التحميل إلى تحميلات غير مكتملة. ماذا تريد أن تفعل؟",
"closeWithActiveUploads": "التحميلات النشطة"
"closeWithActiveUploads": "التحميلات النشطة",
"basicInfo": "معلومات أساسية",
"directoryInfo": "معلومات الدليل",
"additionalInfo": "معلومات إضافية",
"hidden": "مخفي",
"hasPreview": "لديه معاينة",
"checksums": "خانات الشيكات",
"hashAlgorithm": "خوارزمية التجزئة",
"hashValue": "قيمة التجزئة",
"selectHashAlgorithm": "تحديد خوارزمية تجزئة",
"generate": "توليد",
"errorGeneratingHash": "خطأ في توليد التجزئة",
"hashCopied": "التجزئة المنسوخة إلى الحافظة",
"errorCopyingHash": "خطأ في نسخ تجزئة التجزئة",
"token": "الرمز المميز",
"onlyOfficeId": "معرّف المكتب فقط"
},
"search": {
"images": "الصور",
+20 -1
View File
@@ -101,6 +101,10 @@
"noDownloadAccess": "Stahování není k dispozici."
},
"help": {
"functionKeys": "Funkční Klávesy",
"mouseActions": "Akce Myši",
"fileOperations": "Operace se Soubory",
"navigation": "Navigace",
"click": "označit soubor nebo složku",
"ctrl": {
"click": "označit více souborů nebo složek",
@@ -292,7 +296,22 @@
"sourcePath": "Zdroj:",
"destinationPath": "Cílová destinace:",
"closeWithActiveUploadsMessage": "Varování: Upozornění: Máte aktivní nahrávání a zavření výzvy k nahrávání by mohlo vést k nedokončenému nahrávání. Co byste chtěli udělat?",
"closeWithActiveUploads": "Aktivní nahrávání"
"closeWithActiveUploads": "Aktivní nahrávání",
"basicInfo": "Základní informace",
"directoryInfo": "Informace o adresáři",
"additionalInfo": "Další informace",
"hidden": "Skryté stránky",
"hasPreview": "Má náhled",
"checksums": "Kontrolní součty",
"hashAlgorithm": "Algoritmus Hash",
"hashValue": "Hodnota Hash",
"selectHashAlgorithm": "Výběr algoritmu hash",
"generate": "Generovat",
"errorGeneratingHash": "Chyba při generování hash",
"hashCopied": "Hash zkopírovaný do schránky",
"errorCopyingHash": "Chyba při kopírování hash",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Obrázky",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Der Download ist nicht verfügbar."
},
"help": {
"functionKeys": "Funktionstasten",
"mouseActions": "Mausaktionen",
"fileOperations": "Dateioperationen",
"navigation": "Navigation",
"click": "Wähle Datei oder Ordner",
"ctrl": {
"click": "Markiere mehrere Dateien oder Ordner",
@@ -226,7 +230,22 @@
"sourcePath": "Quelle:",
"destinationPath": "Zielort:",
"closeWithActiveUploadsMessage": "Warnung: Sie haben aktive Uploads und das Schließen der Upload-Aufforderung könnte zu unvollendeten Uploads führen. Was würden Sie gerne tun?",
"closeWithActiveUploads": "Aktive Uploads"
"closeWithActiveUploads": "Aktive Uploads",
"basicInfo": "Grundlegende Informationen",
"directoryInfo": "Verzeichnis-Informationen",
"additionalInfo": "Zusätzliche Informationen",
"hidden": "Versteckt",
"hasPreview": "Hat Vorschau",
"checksums": "Prüfsummen",
"hashAlgorithm": "Hash-Algorithmus",
"hashValue": "Hash-Wert",
"selectHashAlgorithm": "Wählen Sie einen Hash-Algorithmus",
"generate": "Erzeugen Sie",
"errorGeneratingHash": "Fehler bei der Hash-Erzeugung",
"hashCopied": "Hash in Zwischenablage kopiert",
"errorCopyingHash": "Fehler beim Kopieren des Hashes",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Bilder",
+20 -1
View File
@@ -101,6 +101,10 @@
"noDownloadAccess": "Η λήψη δεν είναι διαθέσιμη."
},
"help": {
"functionKeys": "Πλήκτρα Λειτουργιών",
"mouseActions": "Ενέργειες Ποντικιού",
"fileOperations": "Λειτουργίες Αρχείων",
"navigation": "Πλοήγηση",
"click": "επιλέξτε αρχείο ή φάκελο",
"ctrl": {
"click": "επιλογή πολλαπλών αρχείων ή φακέλων",
@@ -229,7 +233,22 @@
"sourcePath": "Πηγή:",
"destinationPath": "Προορισμός:",
"closeWithActiveUploadsMessage": "Προειδοποίηση: Το κλείσιμο της προτροπής μεταφόρτωσης μπορεί να οδηγήσει σε ημιτελείς μεταφορτώσεις. Τι θα θέλατε να κάνετε;",
"closeWithActiveUploads": "Ενεργές μεταφορτώσεις"
"closeWithActiveUploads": "Ενεργές μεταφορτώσεις",
"basicInfo": "Βασικές πληροφορίες",
"directoryInfo": "Πληροφορίες καταλόγου",
"additionalInfo": "Πρόσθετες πληροφορίες",
"hidden": "Κρυφό",
"hasPreview": "Έχει προεπισκόπηση",
"checksums": "Αθροίσματα ελέγχου",
"hashAlgorithm": "Αλγόριθμος Hash",
"hashValue": "Αξία κατακερματισμού",
"selectHashAlgorithm": "Επιλέξτε έναν αλγόριθμο κατακερματισμού",
"generate": "Δημιουργία",
"errorGeneratingHash": "Σφάλμα δημιουργίας hash",
"hashCopied": "Αντιγραφή κατακερματισμού στο πρόχειρο",
"errorCopyingHash": "Σφάλμα αντιγραφής hash",
"token": "Token",
"onlyOfficeId": "ΜόνοΤαυτότητα γραφείου"
},
"search": {
"images": "Εικόνες",
+22 -3
View File
@@ -63,7 +63,7 @@
"saveAndExit": "Save and Exit",
"keepEditing": "Keep Editing",
"stayOnPrompt": "Stay",
"closeAnyway": "Close Anyways",
"closeAnyway": "Close Anyways",
"disable": "Disable",
"confirm": "Confirm"
},
@@ -101,6 +101,10 @@
"noDownloadAccess": "Download is not available."
},
"help": {
"functionKeys": "Function Keys",
"mouseActions": "Mouse Actions",
"fileOperations": "File Operations",
"navigation": "Navigation",
"click": "select file or directory",
"ctrl": {
"click": "select multiple files or directories",
@@ -283,7 +287,7 @@
"uploadSettingsNoChunk": "Max concurrent uploads: {maxConcurrentUpload}, chunked upload disabled",
"optionalPassword": "Optional password",
"optionalPasswordHelp": "If set, users must enter this password to view the shared content.",
"typeName": "Type:",
"typeName": "Type",
"deleted": "Deleted successfully!",
"conflictsDetected": "Conflicts detected",
"copyPasteConfirm": "Copy/Paste Confirmation",
@@ -292,7 +296,22 @@
"sourcePath": "Source:",
"destinationPath": "Destination:",
"closeWithActiveUploads": "Active uploads",
"closeWithActiveUploadsMessage": "Warning: You have active uploads and closing the upload prompt could result in unfinished uploads. What would you like to do?"
"closeWithActiveUploadsMessage": "Warning: You have active uploads and closing the upload prompt could result in unfinished uploads. What would you like to do?",
"basicInfo": "Basic Information",
"directoryInfo": "Directory Information",
"additionalInfo": "Additional Information",
"hidden": "Hidden",
"hasPreview": "Has Preview",
"checksums": "Checksums",
"hashAlgorithm": "Hash Algorithm",
"hashValue": "Hash Value",
"selectHashAlgorithm": "Select a hash algorithm",
"generate": "Generate",
"errorGeneratingHash": "Error generating hash",
"hashCopied": "Hash copied to clipboard",
"errorCopyingHash": "Error copying hash",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"searchContext": "Search Context: {context}",
+141 -122
View File
@@ -17,7 +17,7 @@
"new": "Nuevo",
"next": "Siguiente",
"ok": "Aceptar",
"permalink": "Enlace permanente",
"permalink": "Link sin expiración",
"previous": "Anterior",
"publish": "Publicar",
"rename": "Cambiar nombre",
@@ -34,7 +34,7 @@
"switchView": "Cambiar modo de visualización",
"toggleSidebar": "Cambiar visibilidad del panel lateral",
"update": "Actualizar",
"upload": "Subir",
"upload": "Subir archivos",
"openFile": "Abrir archivo",
"copyDownloadLinkToClipboard": "Copiar enlace de descarga",
"continue": "Continuar",
@@ -55,22 +55,22 @@
"compactView": "Compacto",
"normalView": "Normal",
"galleryView": "Galería",
"uploadFiles": "Cargar archivos",
"uploadFolder": "Cargar carpeta",
"openUploadViewer": "Abrir Upload Manager",
"uploadFiles": "Subir archivos",
"uploadFolder": "Subir carpeta",
"openUploadViewer": "Abrir gestor de subidas",
"selectAll": "Seleccionar todo",
"discardAndExit": "Descartar y salir",
"saveAndExit": "Guardar y salir",
"keepEditing": "Seguir editando",
"stayOnPrompt": "Permanezca en",
"closeAnyway": "Cerrar De todos modos",
"stayOnPrompt": "Quedarce",
"closeAnyway": "Cerrar de todos modos",
"disable": "Desactivar",
"confirm": "Confirme"
"confirm": "Confirmar"
},
"download": {
"downloadFile": "Descargar archivo",
"downloadFolder": "Descargar carpeta",
"downloadSelected": "Descargar selección"
"downloadSelected": "Descargar archivos seleccionados"
},
"errors": {
"forbidden": "No tienes permisos para acceder.",
@@ -98,24 +98,28 @@
"noDownloadAccess": "La descarga no está disponible."
},
"help": {
"functionKeys": "Teclas de función",
"mouseActions": "Acciones del mouse",
"fileOperations": "Operaciones de Archivo",
"navigation": "Navegación",
"click": "Selecciona un archivo o carpeta",
"ctrl": {
"click": "Selecciona varios archivos o carpetas (Selección multiple)",
"d": "descargar artículos seleccionados",
"b": "barra lateral",
"comma": "ir a configuración",
"c": "copiar elementos seleccionados",
"v": "pegar elementos copiados o cortados",
"x": "cortar los elementos seleccionados"
"click": "Selecciona varios elementos (Selección multiple)",
"d": "Descargar elementos seleccionados",
"b": "Mostrar/ocultar la barra lateral",
"comma": "Ir a configuración",
"c": "Copiar elementos seleccionados",
"v": "Pegar elementos copiados o cortados",
"x": "Cortar elementos seleccionados"
},
"del": "Eliminar archivos/carpetas seleccionados",
"esc": "Cancela la selección o cierra la ventana actual (ej: Para salir rápido cuando estas viendo una imagen o video)",
"del": "Eliminar elementos seleccionados",
"esc": "Cancela la selección o cierra la ventana actual",
"f2": "Cambiar nombre del archivo o carpeta",
"help": "Ayuda",
"f1": "mostrar mensaje de ayuda",
"description": "A continuación puede ver las opciones básicas de navegación. Para más información, visite",
"slash": "activar búsqueda",
"wiki": "Documentación oficial de FileBrowser Quantum"
"f1": "Abrir ventana de ayuda",
"description": "Aquí puedes ver todos los atajos de teclado básicos. Si quieres saber más, visita la",
"slash": "Activar búsqueda",
"wiki": "documentación oficial de FileBrowser Quantum"
},
"languages": {
"he": "עברית",
@@ -150,7 +154,7 @@
"passwordConfirm": "Confirmar contraseña",
"passwordsDontMatch": "Las contraseñas no coinciden",
"submit": "Iniciar sesión",
"usernameTaken": "Este usuario ya está en uso",
"usernameTaken": "Este usuario ya existe",
"wrongCredentials": "Nombre de usuario y/o contraseña incorrectos",
"or": "O",
"inProgress": "Iniciando sesión...",
@@ -160,7 +164,7 @@
"prompts": {
"copy": "Copiar",
"copyMessage": "Selecciona una ubicación para copiar",
"deleteMessageSingle": "¿Estás seguro que quieres eliminar este archivo/carpeta?",
"deleteMessageSingle": "¿Estás seguro que quieres eliminar este archivo?",
"deleteTitle": "Borrar archivos",
"displayName": "Nombre:",
"download": "Descargar archivos",
@@ -197,36 +201,51 @@
"shareLogo": "Imagen/Logo de la página",
"shareBanner": "Banner de la página",
"shareFavicon": "Mini-icono de la página (favicon)",
"optionalPasswordHelp": "Si eliges una contraseña, los usuarios que accedan deben introducir esa misma contraseña para ver el contenido.",
"optionalPasswordHelp": "Si eliges una contraseña, los usuarios deberán introducir esa misma contraseña para ver el contenido.",
"dragAndDrop": "Arrastra y suelta los archivos aquí",
"completed": "Completado",
"conflictsDetected": "Conflictos detectados",
"viewMode": "Cambiar modo de visualización",
"viewMode": "Cambiar modo de vista",
"renameMessage": "Introduce un nuevo nombre:",
"renameMessageInvalid": "Un archivo no puede contener \"/\" o \"\\\"",
"renameMessageInvalid": "El archivo no puede tener \"/\" o \"\\\"",
"source": "Fuente{suffix}",
"deleteMessageMultiple": "¿Está seguro de que desea eliminar los archivos de {count}?",
"deleteMessageShare": "¿Estás seguro de que quieres borrar esta acción? {path} ?",
"numberDirs": "Número de directorios{suffix}",
"numberFiles": "Número de ficheros{suffix}",
"renameMessageConflict": "Ya existe un elemento llamado \"{filename}\".",
"uploadSettingsChunked": "Carga máxima simultánea: {maxConcurrentUpload} Tamaño del chunk {uploadChunkSizeMb} MB",
"uploadSettingsNoChunk": "Carga máxima simultánea: {maxConcurrentUpload} Carga por trozos desactivada",
"quickJump": "Saltar rápidamente a otros archivos",
"deleteMessageMultiple": "¿Quieres borrar estos {count} archivos?",
"deleteMessageShare": "¿Estás seguro que quieres borrar \"{path}\" de los recursos compartidos?",
"numberDirs": "Número de carpetas {suffix}",
"numberFiles": "Número de archivos {suffix}",
"renameMessageConflict": "Ya existe un archivo llamado \"{filename}\".",
"uploadSettingsChunked": "Subidas simultáneas: {maxConcurrentUpload} - Tamaño de fragmento: {uploadChunkSizeMb} MB",
"uploadSettingsNoChunk": "Subidas simultáneas: {maxConcurrentUpload} - Subida fragmentada: Desactivada",
"quickJump": "Salta rápidamente a otros archivos",
"moveSuccess": "¡Archivos movidos con éxito!",
"copySuccess": "¡Archivos copiados correctamente!",
"lastModified": "Última modificación{suffix}",
"size": "Tamaño {suffix}",
"operationInProgress": "Operación en curso, por favor espere...",
"lastModified": "Última modificación: {suffix}",
"size": "Tamaño: {suffix}",
"operationInProgress": "Operación en curso, espere un momento...",
"saveBeforeExit": "Cambios no guardados",
"saveBeforeExitMessage": "Tienes cambios sin guardar en el editor. ¿Qué desea hacer?",
"copyPasteConfirm": "Confirmación de copiar/pegar",
"copyItemQuestion": "¿Copiar este elemento en la nueva ubicación?",
"moveItemQuestion": "¿Mover este elemento a la nueva ubicación?",
"saveBeforeExitMessage": "Tienes cambios sin guardar. ¿Que quieres hacer?",
"copyPasteConfirm": "Confirmar",
"copyItemQuestion": "¿Quieres copiar este archivo a la nueva ubicación?",
"moveItemQuestion": "¿Quieres mover este archivo a la nueva ubicación?",
"sourcePath": "Fuente:",
"destinationPath": "Destino:",
"closeWithActiveUploadsMessage": "Advertencia: Tienes subidas activas y si cierras el aviso de subidas, podrían quedar subidas inacabadas. ¿Qué desea hacer?",
"closeWithActiveUploads": "Cargas activas"
"destinationPath": "Nueva ubicación:",
"closeWithActiveUploadsMessage": "Si cierras este aviso, todas las subidas activas se interrumpirán, y puede que algunos archivos queden incompletos. ¿Que quieres hacer?",
"closeWithActiveUploads": "Subida de archivos activa",
"basicInfo": "Información básica",
"directoryInfo": "Información del directorio",
"additionalInfo": "Información adicional",
"hidden": "Oculto",
"hasPreview": "Tiene Vista Previa",
"checksums": "Sumas de control",
"hashAlgorithm": "Algoritmo Hash",
"hashValue": "Valor Hash",
"selectHashAlgorithm": "Seleccione un algoritmo hash",
"generate": "Genere",
"errorGeneratingHash": "Error al generar el hash",
"hashCopied": "Hash copiado en el portapapeles",
"errorCopyingHash": "Error al copiar el hash",
"token": "Ficha",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Imágenes",
@@ -238,8 +257,8 @@
"path": "Ruta:",
"smallerThan": "Menor que:",
"largerThan": "Mayor que:",
"helpText1": "La busqueda se realiza por cada carácter (mínimo de 3 caracteres)",
"helpText2": "El índice se actualiza automáticamente (cada 5 min por defecto). Si es interrumpido pueden ocurrir errores",
"helpText1": "La busqueda se realiza por cada letra introducida (empezando de 3)",
"helpText2": "El índice se actualiza automáticamente cada 5 min por defecto. Si se interrumpe pueden haber errores",
"onlyFolders": "Solo carpetas",
"onlyFiles": "Solo archivos",
"showOptions": "Mostrar opciones",
@@ -249,28 +268,28 @@
"documents": "Documentos",
"archives": "Archivos",
"number": "número",
"noResults": "No se han encontrado resultados en la busqueda indexada.",
"searchContext": "Lugares a buscar: {context}",
"notEnoughCharacters": "No hay suficientes caracteres para buscar (min {minSearchLength})",
"typeToSearch": "Escribe {minSearchLength} o más carácteres para iniciar la busqueda."
"noResults": "No pudimos encontrar lo que buscas...",
"searchContext": "Buscar en: {context}",
"notEnoughCharacters": "Escribe al menos {minSearchLength} letras para empezar a buscar",
"typeToSearch": "Escribe {minSearchLength} letras o más para iniciar la búsqueda"
},
"settings": {
"scopes": "Fuentes y directorios que el usuario podrá acceder",
"admin": "Administrador",
"scopes": "Fuentes y carpetas que el usuario tendrá acceso",
"admin": "Admin",
"administrator": "Administrador",
"allowCommands": "Permitir comandos",
"allowEdit": "Editar, borrar, cambiar nombres de archivos o carpetas",
"allowEdit": "Editar, borrar y cambiar nombres de archivos o carpetas",
"allowNew": "Crear nuevos archivos y carpetas",
"allowPublish": "Publicar posts/páginas",
"allowSignup": "Permitir registro de nuevos usuarios",
"avoidChanges": "(dejar en blanco para evitar cambios)",
"branding": "Personalización",
"brandingDirectoryPath": "Directorio de tus archivos que usarás para personalizar FileBrowser",
"brandingDirectoryPath": "Ruta del directorio con los archivos que usarás para personalizar FileBrowser Quantum",
"changePassword": "Cambiar contraseña",
"commandRunner": "Ejecutor de comandos",
"commandsUpdated": "¡Comandos actualizados!",
"createUserDir": "Crea automaticamente una carpeta cuando se agrega un nuevo usuario",
"userHomeBasePath": "Ruta base para los directorios personales de los usuarios",
"userHomeBasePath": "Ruta base para la carpeta personal del usuario",
"userScopeGenerationPlaceholder": "El entorno se generará automáticamente",
"createUserHomeDirectory": "Crea una carpeta personal para cada usuario",
"customStylesheet": "Hoja de estilos personalizada",
@@ -281,10 +300,10 @@
"examples": "Ejemplos",
"executeOnShell": "Ejecutar en la consola de comandos",
"executeOnShellDescription": "FileBrowser ejecuta los comandos directamente de sus binarios. Si quieres ejecutarlos en una consola, puedes definirlo aquí, con los argumentos y banderas (flags) necesarias. El comando ejecutado se añadirá como argumento, tanto a los comandos de usuario, y a los eventos",
"globalRules": "Conjunto global de reglas (permitir y rechazar). Se aplica a todos los usuarios. Puedes definirlas en la configuración de cada usuario si quieres anularlas",
"globalRules": "Conjunto global de reglas (permitir y rechazar). Se aplicará a todos los usuarios. Puedes definirlas en la configuración de cada usuario si quieres anularlas",
"globalSettings": "Configuración global",
"insertPath": "Ingresar ruta",
"insertRegex": "Ingresar regla RegEx",
"insertRegex": "Ingresar regla Regex",
"instanceName": "Nombre de la instancia",
"language": "Idioma",
"lockPassword": "Impedir que el usuario cambie su contraseña",
@@ -306,13 +325,13 @@
"download": "Descargar archivos"
},
"permissions-name": "Permisos",
"permissionsHelp": "Puedes elegir permisos individualmente. Si seleccionas \"Administrador\", todas las demás opciones serán activadas, y los usuarios con ese permiso podrán modificar a otros usuarios.\n",
"permissionsHelp": "Puedes elegir los permisos individualmente. Si seleccionas \"Administrador\", todas las demás opciones serán activadas, y los usuarios administradores podrán modificar a otros usuarios.\n",
"profileSettings": "Ajustes del perfil",
"ruleExample1": "Previene el acceso a una extensión de archivo (ej: .git) en todas las carpetas.\n",
"ruleExample1": "Bloquea el acceso a una extensión especifica extensión de archivo (ej: .git) en todas las carpetas.\n",
"ruleExample2": "Bloquea el acceso al archivo llamado \"Caddyfile\" en la carpeta raíz (/)",
"rules": "Reglas",
"rulesHelp": "Puedes definir un conjunto de reglas de permisos para este usuario específico. Los archivos bloqueados no se mostrarán en las listas y no serán accesibles por el usuario. Puedes utilizar regex y rutas relativas a la raíz del usuario.\n",
"scope": "Raíz",
"rulesHelp": "Puedes definir un conjunto de reglas para este usuario. Los archivos bloqueados no se mostrarán y no serán accesibles pora el usuario. Puedes utilizar regex y rutas relativas al alcance (Ruta base) del usuario.\n",
"scope": "Alcance",
"settingsUpdated": "¡Ajustes actualizados!",
"shareManagement": "Gestión de recursos compartidos",
"shareDeleted": "¡Compartido eliminado!",
@@ -339,10 +358,10 @@
"listingOptions": "Opciones de listado",
"emptyGlobal": "Actualmente no hay configuracion global, edita el archivo YAML para establecer las configuraciones del sistema",
"UserManagement": "Gestión de usuarios",
"tusUploads": "Subir en partes",
"tusUploadsHelp": "File Browser Quantum permite subir archivos en partes, lo que permite que sean subidos de manera eficiente, fiable, que sea reanudable, incluso si tu internet es inestable",
"tusUploadsChunkSize": "Tamaño máximo de subida de un archivo. Puede escribir un número entero que indique una entrada en bytes o una cadena como 10 MB, 1 GB, etc",
"tusUploadsRetryCount": "Número de reintentos, si falla la subida de un archivo",
"tusUploads": "Subida fragmentada",
"tusUploadsHelp": "File Browser Quantum permite subir archivos en fragmentos, lo que permite que sean subidos de manera eficiente, fiable, y que sea reanudable incluso si tu internet es inestable",
"tusUploadsChunkSize": "Tamaño máximo del \"fragmento\" del archivo a subir. Puedes escribir un número en bytes o una cadena como 10 MB, 1 GB, etc",
"tusUploadsRetryCount": "Número de reintentos. Por si falla la subida de algún archivo",
"api": "Claves API",
"loginMethodDescription": "Método de inicio de sesión",
"userNotAdmin": "El usuario no es administrador",
@@ -365,7 +384,7 @@
"configViewerShowFull": "Mostrar configuración completa",
"configViewerShowComments": "Mostrar comentarios",
"configViewerLoadConfig": "Cargar configuración",
"brandingHelp": "Puede personalizar el aspecto de su instancia del Navegador de archivos cambiando su nombre, sustituyendo el logotipo, añadiendo estilos personalizados e incluso desactivando los enlaces externos a GitHub.\nPara obtener más información sobre la personalización de la marca, consulta la página {0}.",
"brandingHelp": "Puedes personalizar la apariencia de FileBrowser Quantum cambiando el nombre, el logo, puedes añadir tus propios estilos personalizados, desactivar los enlaces externos a GitHub, etc. \nSi quieres saber más, visita {0}.",
"commandRunnerHelp": "Aquí puede establecer los comandos que se ejecutan en los eventos nombrados. Debe escribir uno por línea. Las variables de entorno {0} y {1} estarán disponibles, siendo {0} relativa a {1}. Para más información sobre esta característica y las variables de entorno disponibles, por favor lea el {2}."
},
"sidebar": {
@@ -398,25 +417,25 @@
"abortUpload": "¿Cancelar subida?"
},
"share": {
"notice": "Nota: Cuando se crea un recurso compartido, este queda más expuesto al público y tendrá diferentes normas de acceso. Si tu recurso compartido no está configurado de forma segura, cualquiera podrá acceder a él.",
"disableAnonymousDescription": "Cuando está activado, sólo los usuarios con su permiso pueden acceder al recurso compartido. El usuario debe tener acceso al origen recurso compartido.",
"notice": "Nota: Cuando se crea un recurso compartido, este queda más expuesto al público y tendrá diferentes normas de acceso. Si el recurso compartido no está configurado de forma segura, cualquiera podrá acceder a él.",
"disableAnonymousDescription": "Cuando está activado, sólo los usuarios registrados podrán acceder al recurso compartido.",
"disableThumbnailsDescription": "Las miniaturas de archivos, fotos y videos no estarán activadas.",
"enableAllowedUsernamesDescription": "Cuando se activa, sólo los usuarios que especifique pueden acceder al recurso compartido. El usuario debe tener acceso al origen del recurso compartido.",
"downloadsLimitDescription": "Número máximo de veces que se puede descargar un archivo/carpeta del recurso compartido. Dejar vacío para ilimitado.",
"maxBandwidthDescription": "El ancho de banda máximo de descarga en kilobytes por segundo. Dejar vacío para ilimitado.",
"shareThemeDescription": "El tema que se utilizará para el enlace compartido.",
"downloadsLimitDescription": "Número máximo de veces que se puede descargar un archivo/carpeta del recurso compartido - Dejar vacío para ilimitado.",
"maxBandwidthDescription": "El ancho de banda máximo de descarga en kilobytes por segundo - Dejar vacío para ilimitado.",
"shareThemeDescription": "El tema que se utilizará para los usuarios que accedan al recurso compartidos",
"disableAnonymous": "Desactivar el acceso anónimo",
"disableThumbnails": "Desactivar miniaturas",
"enableAllowedUsernames": "Compartir sólo con usuarios predefinidos",
"enableAllowedUsernames": "Compartir sólo con usuarios registrados",
"allowedUsernamesPlaceholder": "Nombres de usuario (separado por comas)",
"keepAfterExpiration": "No eliminar el recurso compartido una vez expirado",
"keepAfterExpirationDescription": "Los recursos compartidos no se borraran cuando expiren. Es útil si después quieres ampliar la duración del recurso, o editarlo.",
"saveDisabled": "No se pueden guardar los cambios en los archivos compartidos.",
"shareDurationDescription": "Tiempo que durará el recurso compartido, puedes dejarlo en blanco para indefinido. (o sea, sin expiración)",
"passwordDescription": "Contraseña opcional necesaria para acceder al recurso compartido, incluidos los usuarios autenticados.",
"shareDurationDescription": "Tiempo que durará el recurso compartido - puedes dejarlo en blanco para indefinido (o sea, sin expiración).",
"passwordDescription": "Contraseña opcional necesaria para acceder al recurso compartido, incluyedo usuarios registrados",
"allowedUsernamesListDescription": "Nombres de usuario separados por comas que pueden acceder al recurso compartido (si está activado).",
"shareThemeColorDescription": "Valor de color CSS aplicado al tema de la acción (por ejemplo, rojo, #0ea5e9, rgb(14,165,233)).",
"shareTitleDescription": "Título de página personalizado de página",
"shareTitleDescription": "Título de la página que se mostrará en el navegador",
"shareDescriptionHelp": "Breve descripción mostrada en la página (que suele aparecer cuando compartes el enlace)",
"shareLogoDescription": "Enlace (URL), o ruta de la imagen del logo que se mostrará en el enlace -- por ejemplo, 'https://ejemplo.com/logo.png' o '/ruta/a/logo.png'.",
"shareBannerDescription": "Enlace (URL), o ruta de la imagen del banner que se mostrará en el enlace -- por ejemplo, 'https://ejemplo.com/banner.png' o '/ruta/a/banner.png'.",
@@ -424,31 +443,31 @@
"hideNavButtons": "Ocultar botones de navegación",
"hideNavButtonsDescription": "Oculta los botones de navegación en la parte superior, es útil si quieres crear un aspecto minimalista.",
"viewModeDescription": "Diseño por defecto de la página compartida.",
"descriptionDefault": "Se le ha enviado una acción para que la vea o descargue.",
"disableShareCard": "Desactiva la opción de compartir en la página",
"disableShareCardDescription": "Desactivar la tarjeta de compartir en la página compartida en el panel lateral o en la parte superior de la página en móvil.",
"descriptionDefault": "Han compartido esto contigo.",
"disableShareCard": "Desactivar código QR",
"disableShareCardDescription": "Desactiva el código QR en el panel lateral o en la parte superior de la página en móvil",
"disableSidebar": "Desactivar el panel lateral",
"disableSidebarDescription": "Desactivar el panel lateral en la página compartida.",
"disableFileViewer": "Desactivar visor de archivos",
"enforceDarkLightMode": "Tema",
"enforceDarkLightModeDescription": "Forzar un modo de tema específico (oscuro o claro) para esta acción, anulando las preferencias del usuario.",
"default": "Automatico",
"enforceDarkLightModeDescription": "Forzar un modo de tema específico (oscuro o claro) para el recurso compartido, anulando las preferencias del usuario.",
"default": "Por defecto",
"dark": "Oscuro",
"light": "Claro",
"enableOnlyOffice": "Activar el visor de OnlyOffice",
"enableOnlyOfficeDescription": "Permitir la visualización de archivos de oficina utilizando OnlyOffice en este recurso compartido.",
"titleDefault": "Archivos compartidos - {title}",
"titleDefault": "{title}",
"defaultViewMode": "Modo de visualización",
"defaultViewModeDescription": "Establece el modo de visualización predeterminado para los usuarios anónimos que vean esta acción. Los usuarios registrados pueden cambiar su preferencia de visualización.",
"shareType": "Tipo de acción",
"shareTypeDescription": "El tipo de recurso compartido que se va a crear. Los recursos compartidos normales permiten ver y descargar archivos. Los recursos compartidos de carga permiten cargar archivos en el recurso compartido.",
"shareType": "Tipo de compartido",
"shareTypeDescription": "El tipo de recurso compartido que se va a crear. Los recursos compartidos normales permiten ver y descargar archivos. Los recursos compartidos de subida permiten subir archivos al recurso compartido.",
"normalShare": "Normal",
"uploadShare": "Cargar sólo",
"perUserDownloadLimit": "Aplicar el límite de descargas a cada usuario",
"uploadShare": "Solo subidas",
"perUserDownloadLimit": "Límitar descargas para cada usuario",
"perUserDownloadLimitDescription": "Cuando se activa, el límite de descargas se aplicará a cada usuario. Los usuarios anónimos no podrán descargar ningún archivo de este recurso compartido.",
"descriptionUploadDefault": "Se le ha enviado una acción para cargar archivos.",
"descriptionUploadDefault": "Te han compartido un enlace para que subas archivos",
"extractEmbeddedSubtitles": "Extraer subtítulos incrustados",
"extractEmbeddedSubtitlesDescription": "Extrae los subtítulos incrustados de los archivos multimedia al cargarlos -- esto puede ser lento para archivos grandes.",
"extractEmbeddedSubtitlesDescription": "Extrae los subtítulos incrustados de los archivos multimedia al cargarlos -- esto puede ser lento si el archivo es grande.",
"disableDownload": "Desactivar la descarga de archivos",
"disableDownloadDescription": "Nadie podrá descargar archivos ni ver su contenido.",
"allowModify": "Permitir la edición de archivos",
@@ -456,9 +475,9 @@
"allowDelete": "Permitir la eliminación de archivos",
"allowDeleteDescription": "Cualquiera puede borrar archivos y carpetas de este recurso compartido.",
"allowReplacements": "Permitir la sustitución de archivos",
"allowReplacementsDescription": "Cualquiera puede sustituir archivos existentes al cargar archivos con el mismo nombre.",
"allowCreate": "Permitir crear y cargar archivos y carpetas",
"allowCreateDescription": "Cualquiera puede crear y cargar nuevos archivos y carpetas en este recurso compartido."
"allowReplacementsDescription": "Cualquiera podrá reemplazar archivos existentes al subir archivos con el mismo nombre.",
"allowCreate": "Permitir crear/subir archivos y carpetas",
"allowCreateDescription": "Cualquiera puede crear/subir nuevos archivos y carpetas en este recurso compartido."
},
"api": {
"title": "Gestión de claves API",
@@ -496,7 +515,7 @@
"toggleDark": "Activar modo oscuro",
"toggleSticky": "Cambiar visibilidad del panel lateral",
"used": "usado",
"noSources": "No hay fuentes disponibles. Añada una o active defaultEnabled: true."
"noSources": "No hay fuentes disponibles. Añada una o active \"defaultEnabled: true\" en el archivo de configuración."
},
"otp": {
"name": "Autenticación de dos factores (2FA)",
@@ -507,19 +526,19 @@
"enabledSuccessfully": "¡2FA activado!",
"verificationFailed": "Verificación fallida",
"verificationSucceed": "Verificación exitosa",
"generationFailed": "La generación falló"
"generationFailed": "La generación del código falló"
},
"general": {
"name": "Nombre",
"path": "Ruta",
"user": "Usuario",
"group": "Grupo",
"signup": "Regístrese en",
"signup": "Regístrarse",
"password": "Contraseña",
"username": "Nombre de usuario",
"files": "Archivos",
"folders": "Carpetas",
"exit": "Salida",
"exit": "Salir",
"permanent": "Permanente",
"hash": "Hash",
"of": "de"
@@ -527,8 +546,8 @@
"access": {
"rules": "Normas de acceso",
"deny": "Denegar",
"deniedUsers": "Usuarios rechazados",
"deniedGroups": "Grupos rechazados",
"deniedUsers": "Usuarios denegados",
"deniedGroups": "Grupos denegados",
"allowedUsers": "Usuarios permitidos",
"allowedGroups": "Grupos permitidos",
"allow": "Permitir",
@@ -542,18 +561,18 @@
"totalDenied": "Denegado",
"totalAllowed": "Permitido",
"all": "Denegar todo",
"defaultBehaviorDescription": "Muestra lo que ocurre cuando un usuario intenta acceder a una ruta en la que no existen reglas de acceso específicas. Permitir\" significa que los usuarios pueden acceder por defecto, \"Denegar\" significa que los usuarios están bloqueados por defecto a menos que se les permita explícitamente.",
"defaultBehavior": "Acción por defecto{suffix}"
"defaultBehaviorDescription": "Muestra lo que ocurre cuando un usuario intenta acceder a una ruta en la que no existen reglas de acceso específicas -- \"Permitir\" significa que los usuarios pueden acceder (por defecto), \"Denegar\" significa que los usuarios están bloqueados (por defecto) a menos que se les permita explícitamente.",
"defaultBehavior": "Acción por defecto {suffix}"
},
"fileLoading": {
"title": "Carga de archivos",
"maxConcurrentUpload": "Cargas máximas simultáneas",
"title": "Subir archivos",
"maxConcurrentUpload": "Subidas a la vez",
"maxConcurrentUploadHelp": "El número máximo de archivos a subir a la vez. Los valores más altos suelen dar mejores resultados, pero esto depende de muchos factores",
"uploadChunkSizeMb": "Velocidad de subida (en MB)",
"uploadChunkSizeMbHelp": "Típicamente 5 a 50 MB, más pequeño es mejor para conexiones inestables. Si se pone a 0, se desactiva la subida de archivo en partes",
"clearAll": " Hacer que 'Limpiar completados' borre todo (incluyendo error, pausa y en conflicto)",
"clearAllDescription": "El botón de borrado de cargas completadas borrará todas las cargas en estado finalizado, incluidos los estados de error, pausa y conflicto.",
"uploadSettings": "Cargar configuración"
"uploadChunkSizeMbHelp": "Típicamente 5 a 50 MB, más pequeño es mejor para conexiones inestables.",
"clearAll": "Hacer que \"Limpiar completados\" borre todo (incluyendo error, pausa y en conflicto)",
"clearAllDescription": "El botón de borrado de \"subidas completadas\" borrará todas los archivos subidos en todos los estados: Finalizado, error, pausa y conflicto.",
"uploadSettings": "Configuracion de subidas"
},
"colors": {
"red": "Rojo",
@@ -565,9 +584,9 @@
},
"profileSettings": {
"autoplayMedia": "Reproducción automática de archivos multimedia",
"autoplayMediaDescription": "Reproducción automática de archivos multimedia al visualizarlos. Esto sólo funcionará si el archivo es un archivo multimedia",
"autoplayMediaDescription": "Reproduce automaticamente los archivos multimedia al abrirlos",
"sidebarOptions": "Opciones del panel lateral",
"editorViewerOptions": "Edición y visualización",
"editorViewerOptions": "Opciones del editor",
"editorQuickSave": "Botón de guardado rápido en el editor",
"editorQuickSaveDescription": "El editor de texto mostrará siempre el icono de guardar, ocultando cualquier otra acción",
"previewOffice": "Mostrar miniaturas para los archivos de Office",
@@ -576,14 +595,14 @@
"disableThumbnailPreviewsDescription": "Una lista (separada por espacios) de extensiones de archivo para desactivar la vista previa en las miniaturas (por ejemplo, '.txt .html').",
"disableViewingFiles": "Desactivar el visor/editor de archivos para las siguientes extensiones:",
"disableViewingFilesDescription": "Una lista (separada por espacios) de extensiones de archivo para desactivar el visor/editor de archivos (por ejemplo, '.txt .pdf').",
"disablePreviewExt": "Desactivar la vista previa de archivos de Ofimática para las siguientes extensiones:",
"disablePreviewExt": "Desactivar la vista previa de archivos de Office para las siguientes extensiones:",
"disablePreviewExtDescription": "Una lista (separada por espacios) de las extensiones de archivo para las que se desactivará la vista previa de los archivos de Office (por ejemplo, '.docx .pptx').",
"disableOfficeEditorDescription": "Una lista (separada por espacios) de las extensiones de archivo para las que desea desactivar el editor y el visor de OnlyOffice. (por ejemplo, '.txt .html .pdf').",
"disableOfficeEditor": "Desactivar el visor y editor de office para las siguientes extensiones:",
"defaultThemeDescription": "Predeterminado",
"customTheme": "Cambiar tema",
"showSelectMultiple": "Mostrar selección múltiple en el menú contextuaL (en PC)",
"showSelectMultipleDescription": "Por defecto, el menú contextual del escritorio no tiene la opción \"seleccionar múltiples\" como el móvil. Esta opción siempre se muestra en el menú contextual.",
"showSelectMultiple": "Mostrar selección múltiple en el menú contextual (en PC)",
"showSelectMultipleDescription": "Por defecto, el menú contextual en PC no tiene la opción \"selección multiple\" como en móvil. Esta opción hará que aparezca siempre.",
"setDateFormat": "Usar fecha exacta (DD/MM/AA)",
"showHiddenFiles": "Mostrar archivos ocultos",
"showHiddenFilesDescription": "Muestra los archivos ocultos. (por ejemplo, .thumbnails, ProgramData), pero siguen siendo accesibles manualmente si están configurados para ser indexados.",
@@ -604,8 +623,8 @@
"filePreviewOptions": "Opciones de previsualización de archivos",
"disableUpdateNotifications": "Desactivar las notificaciones de actualización",
"disableUpdateNotificationsDescription": "Desactivar el banner de notificación de actualización que aparece para los usuarios administradores en el panel lateral.",
"disableHideSidebar": "Mantener el panel lateral abierto al previsualizar o editar archivos",
"disableHideSidebarDescription": "Si está activado, el panel lateral no se ocultará automáticamente al previsualizar o editar archivos.",
"disableHideSidebar": "Mantener el panel lateral abierto al visualizar o editar archivos",
"disableHideSidebarDescription": "Si está activado, el panel lateral no se ocultará automáticamente al visualizar o editar archivos.",
"disableQuickToggles": "Desactivar ajustes rápidos",
"disableQuickTogglesDescription": "Desactiva los ajustes rápidos que aparecen en el panel lateral. (cambiar tema, visibilidad del panel y modo de un solo click)",
"disableSearchOptions": "Desactivar las opciones de busqueda",
@@ -615,28 +634,28 @@
"deleteWithoutConfirming": "Eliminar archivos sin mensaje de confirmación",
"deleteWithoutConfirmingDescription": "Eliminar archivos sin mensaje de confirmación. Esto sólo funcionará si el archivo es un archivo multimedia.",
"defaultMediaPlayer": "Usar el reproductor multimedia nativo del navegador",
"defaultMediaPlayerDescription": "Usar el reproductor multimedia nativo de tu navegador para los archivos de vídeo y audio en lugar del reproductor multimedia incluido en FileBrowser.",
"defaultMediaPlayerDescription": "Usar el reproductor multimedia nativo de tu navegador para los archivos de vídeo y audio en lugar del reproductor multimedia incluido en FileBrowser Quantum.",
"debugOfficeEditor": "Activar el modo de depuración de OnlyOffice",
"debugOfficeEditorDescription": "Mostrar una ventana emergente de depuración con información adicional en el editor OnlyOffice.",
"fileViewerOptions": "Opciones del visor de archivos",
"themeAndLanguage": "Tema e idioma",
"previewFolder": "Vista previa para carpetas (si se puede)",
"previewFolderDescription": "Mostrar vistas previas en miniatura para las carpetas - Se usará el primer elemento como portada. (puede ser una imagen, o audio con imagén)",
"defaultLandingPage": "Página de destino predeterminada",
"defaultLandingPageDescription": "Ej. '/files/mysource/mysubpath' o '/settings' - la página por defecto es /files que va a la primera vista del listado de fuentes."
"themeAndLanguage": "Tema e Idioma",
"previewFolder": "Vista previa en miniatura para carpetas",
"previewFolderDescription": "Mostrar vistas previas en miniatura para las carpetas - Se usará el primer elemento como portada. (puede ser una imagen, o audio con imagen)",
"defaultLandingPage": "Página de inicio predeterminada",
"defaultLandingPageDescription": "Ej. '/files/miCarpeta/MiSubfolder' o '/settings' - la página por defecto es /files que va a la primera vista del listado de fuentes."
},
"editor": {
"uninitialized": "Error al iniciar el editor, inténtelo de nuevo",
"uninitialized": "Hubo un error al iniciar el editor",
"saveFailed": "No se ha podido guardar el archivo. Por favor, inténtelo de nuevo.",
"saveAborted": "No se ha podido guardar el archivo. El nombre del archivo no coincide con el que estás editando.",
"saveAbortedMessage": "Operación de guardado abortada. El archivo activo de la aplicación ({activeFile}) no coincide con el archivo que está intentando guardar ({tryingToSave}).",
"syncFailed": "No se ha podido sincronizar el estado con la ruta para \"{filename}\" después de 5 intentos. Abortar la configuración del editor para evitar la corrupción de datos."
"saveAbortedMessage": "Operación de guardado abortada. El archivo activo ({activeFile}) no coincide con el que estas intentando guardar ({tryingToSave}).",
"syncFailed": "No se ha podido sincronizar el estado con la ruta para \"{filename}\" después de 5 intentos - Se abortará la configuración del editor para evitar la corrupción de datos."
},
"player": {
"LoopEnabled": "Bucle activado",
"LoopDisabled": "Bucle desactivado",
"PlayAllOncePlayback": "Reproducir todo una vez",
"ShuffleAllPlayback": "Reproducir todo aleatoriamente",
"ShuffleAllPlayback": "Reproducción aleatoria",
"PlayAllLoopedPlayback": "Reproducir todo en bucle",
"QueueButtonHint": "Mostrar cola de Reproducción",
"QueuePlayback": "Cola de Reproducción",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Le téléchargement n'est pas disponible."
},
"help": {
"functionKeys": "Touches de Fonction",
"mouseActions": "Actions de la Souris",
"fileOperations": "Opérations sur les Fichiers",
"navigation": "Navigation",
"click": "sélectionner un élément",
"ctrl": {
"click": "sélectionner plusieurs éléments",
@@ -226,7 +230,22 @@
"sourcePath": "Source :",
"destinationPath": "Destination :",
"closeWithActiveUploadsMessage": "Attention : Vous avez des téléchargements actifs et la fermeture de l'invite de téléchargement pourrait entraîner des téléchargements inachevés. Que voulez-vous faire ?",
"closeWithActiveUploads": "Téléchargements actifs"
"closeWithActiveUploads": "Téléchargements actifs",
"basicInfo": "Informations de base",
"directoryInfo": "Informations sur l'annuaire",
"additionalInfo": "Informations complémentaires",
"hidden": "Caché",
"hasPreview": "Avant-première",
"checksums": "Sommes de contrôle",
"hashAlgorithm": "Algorithme de hachage",
"hashValue": "Valeur de hachage",
"selectHashAlgorithm": "Sélectionner un algorithme de hachage",
"generate": "Générer",
"errorGeneratingHash": "Erreur dans la génération du hachage",
"hashCopied": "Hash copié dans le presse-papiers",
"errorCopyingHash": "Erreur de copie du hachage",
"token": "Jeton",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Images",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "ההורדה אינה זמינה."
},
"help": {
"functionKeys": "מקשי פונקציה",
"mouseActions": "פעולות עכבר",
"fileOperations": "פעולות קבצים",
"navigation": "ניווט",
"click": "בחר קובץ או תקייה",
"ctrl": {
"click": "בחר מספר קבצים או תקיות",
@@ -226,7 +230,22 @@
"sourcePath": "מקור:",
"destinationPath": "יעד:",
"closeWithActiveUploadsMessage": "אזהרה: יש לך העלאות פעילות וסגירת חלון ההעלאה עלולה לגרום להשלמת העלאות לא גמורות. מה ברצונך לעשות?",
"closeWithActiveUploads": "העלאות פעילות"
"closeWithActiveUploads": "העלאות פעילות",
"basicInfo": "מידע בסיסי",
"directoryInfo": "מידע על ספריות",
"additionalInfo": "מידע נוסף",
"hidden": "נסתר",
"hasPreview": "יש תצוגה מקדימה",
"checksums": "סכומים מבוקרים",
"hashAlgorithm": "אלגוריתם hash",
"hashValue": "ערך hash",
"selectHashAlgorithm": "בחר אלגוריתם hash",
"generate": "ליצור",
"errorGeneratingHash": "שגיאה ביצירת hash",
"hashCopied": "ה-hash הועתק ללוח",
"errorCopyingHash": "שגיאה בהעתקת hash",
"token": "אסימון",
"onlyOfficeId": "מזהה OnlyOffice"
},
"search": {
"images": "תמונות",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "A letöltés nem elérhető."
},
"help": {
"functionKeys": "Funkcióbillentyűk",
"mouseActions": "Egérműveletek",
"fileOperations": "Fájlműveletek",
"navigation": "Navigáció",
"click": "mappa vagy fájl kijelölése",
"ctrl": {
"click": "több mappa vagy fájl kijelölése",
@@ -226,7 +230,22 @@
"sourcePath": "Forrás:",
"destinationPath": "Úti cél:",
"closeWithActiveUploadsMessage": "Figyelmeztetés: A feltöltési prompt bezárása befejezetlen feltöltéseket eredményezhet. Mit szeretne tenni?",
"closeWithActiveUploads": "Aktív feltöltések"
"closeWithActiveUploads": "Aktív feltöltések",
"basicInfo": "Alapvető információk",
"directoryInfo": "Címtár információk",
"additionalInfo": "További információk",
"hidden": "Rejtett",
"hasPreview": "Van előnézet",
"checksums": "Ellenőrző összegek",
"hashAlgorithm": "Hash algoritmus",
"hashValue": "Hash érték",
"selectHashAlgorithm": "Válasszon ki egy hash algoritmust",
"generate": "Generálja",
"errorGeneratingHash": "Hiba generáló hash",
"hashCopied": "Hash másolva a vágólapra",
"errorCopyingHash": "Hiba a hash másolásában",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Képek",
+4
View File
@@ -92,6 +92,10 @@
"noPreview": "Forskoðun er ekki í boði fyrir þessa skrá."
},
"help": {
"functionKeys": "Virknislyklar",
"mouseActions": "Músaraðgerðir",
"fileOperations": "Skráaðgerðir",
"navigation": "Flakk",
"click": "velja skrá eða möppu",
"ctrl": {
"click": "velja margar skrár eða möppur",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Il download non è disponibile."
},
"help": {
"functionKeys": "Tasti Funzione",
"mouseActions": "Azioni del Mouse",
"fileOperations": "Operazioni sui File",
"navigation": "Navigazione",
"click": "seleziona un file o una cartella",
"ctrl": {
"click": "seleziona più file o cartelle",
@@ -226,7 +230,22 @@
"sourcePath": "Fonte:",
"destinationPath": "Destinazione:",
"closeWithActiveUploadsMessage": "Attenzione: Ci sono caricamenti attivi e la chiusura del prompt di caricamento potrebbe causare caricamenti non completati. Cosa si desidera fare?",
"closeWithActiveUploads": "Carichi attivi"
"closeWithActiveUploads": "Carichi attivi",
"basicInfo": "Informazioni di base",
"directoryInfo": "Informazioni sull'elenco",
"additionalInfo": "Informazioni aggiuntive",
"hidden": "Nascosto",
"hasPreview": "Ha Anteprima",
"checksums": "Checksum",
"hashAlgorithm": "Algoritmo Hash",
"hashValue": "Valore Hash",
"selectHashAlgorithm": "Selezionare un algoritmo di hash",
"generate": "Generare",
"errorGeneratingHash": "Errore nella generazione dell'hash",
"hashCopied": "Hash copiato negli appunti",
"errorCopyingHash": "Errore nella copia dell'hash",
"token": "Gettone",
"onlyOfficeId": "Solo ID ufficio"
},
"search": {
"images": "Immagini",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "ダウンロードはできません。"
},
"help": {
"functionKeys": "ファンクションキー",
"mouseActions": "マウス操作",
"fileOperations": "ファイル操作",
"navigation": "ナビゲーション",
"click": "ファイルやディレクトリを選択",
"ctrl": {
"click": "複数のファイルやディレクトリを選択",
@@ -226,7 +230,22 @@
"sourcePath": "ソース",
"destinationPath": "目的地だ:",
"closeWithActiveUploadsMessage": "警告アクティブなアップロードがあり、アップロードプロンプトを閉じるとアップロードが未完了になる可能性があります。どうしますか?",
"closeWithActiveUploads": "アクティブなアップロード"
"closeWithActiveUploads": "アクティブなアップロード",
"basicInfo": "基本情報",
"directoryInfo": "ディレクトリ情報",
"additionalInfo": "追加情報",
"hidden": "ヒドゥン",
"hasPreview": "プレビュー",
"checksums": "チェックサム",
"hashAlgorithm": "ハッシュ・アルゴリズム",
"hashValue": "ハッシュ値",
"selectHashAlgorithm": "ハッシュアルゴリズムの選択",
"generate": "生成する",
"errorGeneratingHash": "ハッシュ生成エラー",
"hashCopied": "クリップボードにコピーされたハッシュ",
"errorCopyingHash": "ハッシュのコピーエラー",
"token": "トークン",
"onlyOfficeId": "オンリーオフィスID"
},
"search": {
"images": "画像",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "다운로드할 수 없습니다."
},
"help": {
"functionKeys": "기능 키",
"mouseActions": "마우스 작업",
"fileOperations": "파일 작업",
"navigation": "탐색",
"click": "파일이나 디렉토리를 선택해주세요.",
"ctrl": {
"click": "여러 개의 파일이나 디렉토리를 선택해주세요.",
@@ -226,7 +230,22 @@
"sourcePath": "출처:",
"destinationPath": "목적지:",
"closeWithActiveUploadsMessage": "경고: 업로드가 진행 중이며 업로드 프롬프트를 닫으면 완료되지 않은 업로드가 발생할 수 있습니다. 어떻게 하시겠습니까?",
"closeWithActiveUploads": "활성 업로드"
"closeWithActiveUploads": "활성 업로드",
"basicInfo": "기본 정보",
"directoryInfo": "디렉토리 정보",
"additionalInfo": "추가 정보",
"hidden": "숨겨진",
"hasPreview": "미리보기 있음",
"checksums": "체크섬",
"hashAlgorithm": "해시 알고리즘",
"hashValue": "해시 값",
"selectHashAlgorithm": "해시 알고리즘 선택",
"generate": "생성",
"errorGeneratingHash": "해시 생성 오류",
"hashCopied": "클립보드에 해시 복사",
"errorCopyingHash": "해시 복사 오류",
"token": "토큰",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "이미지",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Download is niet beschikbaar."
},
"help": {
"functionKeys": "Functietoetsen",
"mouseActions": "Muisacties",
"fileOperations": "Bestandsbewerkingen",
"navigation": "Navigatie",
"click": "selecteer bestand of map",
"ctrl": {
"click": "selecteer meerdere bestanden of mappen",
@@ -226,7 +230,22 @@
"sourcePath": "Bron:",
"destinationPath": "Bestemming:",
"closeWithActiveUploadsMessage": "Waarschuwing: U hebt actieve uploads en het sluiten van de uploadprompt kan resulteren in onvoltooide uploads. Wat wilt u doen?",
"closeWithActiveUploads": "Actieve uploads"
"closeWithActiveUploads": "Actieve uploads",
"basicInfo": "Basisinformatie",
"directoryInfo": "Adresboekinformatie",
"additionalInfo": "Aanvullende informatie",
"hidden": "Verborgen",
"hasPreview": "Voorbeeld",
"checksums": "Controlesommen",
"hashAlgorithm": "Hash-algoritme",
"hashValue": "Hashwaarde",
"selectHashAlgorithm": "Selecteer een hash-algoritme",
"generate": "genereren",
"errorGeneratingHash": "Fout bij het genereren van hash",
"hashCopied": "Hash gekopieerd naar klembord",
"errorCopyingHash": "Fout bij het kopiëren van hash",
"token": "Penning",
"onlyOfficeId": "Alleen kantoor-ID"
},
"search": {
"images": "Afbeeldingen",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Pobieranie nie jest dostępne."
},
"help": {
"functionKeys": "Klawisze Funkcji",
"mouseActions": "Akcje Myszy",
"fileOperations": "Operacje na Plikach",
"navigation": "Nawigacja",
"click": "wybierz plik lub foler",
"ctrl": {
"click": "wybierz wiele plików lub folderów",
@@ -226,7 +230,22 @@
"sourcePath": "Źródło:",
"destinationPath": "Miejsce docelowe:",
"closeWithActiveUploadsMessage": "Ostrzeżenie: Masz aktywne przesyłanie, a zamknięcie monitu o przesłanie może spowodować niedokończone przesyłanie. Co chcesz zrobić?",
"closeWithActiveUploads": "Aktywne przesyłanie"
"closeWithActiveUploads": "Aktywne przesyłanie",
"basicInfo": "Podstawowe informacje",
"directoryInfo": "Informacje katalogowe",
"additionalInfo": "Dodatkowe informacje",
"hidden": "Ukryty",
"hasPreview": "Ma podgląd",
"checksums": "Sumy kontrolne",
"hashAlgorithm": "Algorytm Hash",
"hashValue": "Wartość skrótu",
"selectHashAlgorithm": "Wybór algorytmu skrótu",
"generate": "Generowanie",
"errorGeneratingHash": "Błąd generowania skrótu",
"hashCopied": "Hash skopiowany do schowka",
"errorCopyingHash": "Błąd kopiowania skrótu",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Zdjęcia",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "O download não está disponível."
},
"help": {
"functionKeys": "Teclas de Função",
"mouseActions": "Ações do Mouse",
"fileOperations": "Operações de Arquivos",
"navigation": "Navegação",
"click": "selecionar pasta ou arquivo",
"ctrl": {
"click": "selecionar várias pastas e arquivos",
@@ -226,7 +230,22 @@
"sourcePath": "Fonte:",
"destinationPath": "Destino:",
"closeWithActiveUploadsMessage": "Aviso: Você tem uploads ativos e fechar o prompt de upload pode resultar em uploads inacabados. O que você gostaria de fazer?",
"closeWithActiveUploads": "Uploads ativos"
"closeWithActiveUploads": "Uploads ativos",
"basicInfo": "Informações básicas",
"directoryInfo": "Informações de diretório",
"additionalInfo": "Informações adicionais",
"hidden": "Oculto",
"hasPreview": "Tem Prévia",
"checksums": "Checksums",
"hashAlgorithm": "Algoritmo de hash",
"hashValue": "Valor Hash",
"selectHashAlgorithm": "Selecione um algoritmo de hash",
"generate": "Gerar",
"errorGeneratingHash": "Erro ao gerar hash",
"hashCopied": "Hash copiado para a área de transferência",
"errorCopyingHash": "Erro ao copiar o hash",
"token": "Token",
"onlyOfficeId": "ID do OnlyOffice"
},
"search": {
"images": "Imagens",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "A transferência não está disponível."
},
"help": {
"functionKeys": "Teclas de Função",
"mouseActions": "Ações do Rato",
"fileOperations": "Operações de Ficheiros",
"navigation": "Navegação",
"click": "selecionar pasta ou ficheiro",
"ctrl": {
"click": "selecionar várias pastas e ficheiros",
@@ -226,7 +230,22 @@
"sourcePath": "Fonte:",
"destinationPath": "Destino:",
"closeWithActiveUploadsMessage": "Aviso: Tem carregamentos activos e fechar a janela de carregamento pode resultar em carregamentos inacabados. O que é que gostaria de fazer?",
"closeWithActiveUploads": "Carregamentos activos"
"closeWithActiveUploads": "Carregamentos activos",
"basicInfo": "Informações básicas",
"directoryInfo": "Informações sobre o diretório",
"additionalInfo": "Informações adicionais",
"hidden": "Oculto",
"hasPreview": "Tem Pré-visualização",
"checksums": "Somas de controlo",
"hashAlgorithm": "Algoritmo de Hash",
"hashValue": "Valor de hash",
"selectHashAlgorithm": "Selecionar um algoritmo de hash",
"generate": "Gerar",
"errorGeneratingHash": "Erro ao gerar hash",
"hashCopied": "Hash copiado para a área de transferência",
"errorCopyingHash": "Erro ao copiar o hash",
"token": "Ficha",
"onlyOfficeId": "ID do OnlyOffice"
},
"search": {
"images": "Imagens",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Descărcarea nu este disponibilă."
},
"help": {
"functionKeys": "Taste Funcție",
"mouseActions": "Acțiuni Mouse",
"fileOperations": "Operații Fișiere",
"navigation": "Navigare",
"click": "alege fișier sau director",
"ctrl": {
"click": "alege multiple fișiere sau directoare",
@@ -226,7 +230,22 @@
"sourcePath": "Sursă:",
"destinationPath": "Destinație:",
"closeWithActiveUploadsMessage": "Atenție: Aveți încărcări active și închiderea solicitării de încărcare ar putea duce la încărcări neterminate. Ce ați dori să faceți?",
"closeWithActiveUploads": "Încărcări active"
"closeWithActiveUploads": "Încărcări active",
"basicInfo": "Informații de bază",
"directoryInfo": "Informații din director",
"additionalInfo": "Informații suplimentare",
"hidden": "Ascunse",
"hasPreview": "Are Previzualizare",
"checksums": "Verificări",
"hashAlgorithm": "Algoritmul Hash",
"hashValue": "Valoare Hash",
"selectHashAlgorithm": "Selectați un algoritm hash",
"generate": "Generați",
"errorGeneratingHash": "Eroare în generarea hash-ului",
"hashCopied": "Hash copiat în clipboard",
"errorCopyingHash": "Eroare copiere hash",
"token": "Token",
"onlyOfficeId": "NumaiOffice ID"
},
"search": {
"images": "Imagini",
+67 -48
View File
@@ -36,40 +36,40 @@
"update": "Обновить",
"upload": "Загрузить",
"openFile": "Открыть файл",
"copyDownloadLinkToClipboard": "Скопируйте ссылку на скачивание в буфер обмена",
"copyDownloadLinkToClipboard": "Скопировать ссылку для скачивания в буфер обмена",
"continue": "Продолжить",
"edit": "Редактировать",
"generateNewOtp": "Сброс и генерация нового двухфакторного кода",
"verify": "Проверьте",
"verify": "Проверить",
"pause": "Пауза",
"resume": "Резюме",
"resume": "Возобновить",
"retry": "Повторная попытка",
"pauseAll": "Приостановить все",
"resumeAll": "Резюме все",
"clearCompleted": "Очистка завершена",
"resumeAll": "Возобновить все",
"clearCompleted": "Очистить завершенные",
"showMore": "Показать еще",
"showLess": "Показать меньше",
"openParentFolder": "Откройте родительскую папку",
"openParentFolder": "Открыть родительскую папку",
"selectedCount": "Количество элементов, выбранных для выполнения действия",
"listView": "Вид списка",
"compactView": "Компактный вид",
"normalView": "Обычный вид",
"galleryView": "Вид галереи",
"uploadFiles": "Загрузка файлов",
"uploadFolder": "Папка для загрузки",
"openUploadViewer": "Откройте менеджер загрузки",
"uploadFiles": "Загрузить файлы",
"uploadFolder": "Загрузить папку",
"openUploadViewer": "Открыть менеджер загрузки",
"selectAll": "Выбрать все",
"discardAndExit": "Выброс и выход",
"discardAndExit": "Отменить и выйти",
"saveAndExit": "Сохранить и выйти",
"keepEditing": "Продолжайте редактировать",
"stayOnPrompt": "Оставайтесь",
"closeAnyway": "Близко в любом случае",
"keepEditing": "Продолжить редактирование",
"stayOnPrompt": "Остаться",
"closeAnyway": "Закрыть в любом случае",
"disable": "Отключить",
"confirm": "Подтвердите"
},
"download": {
"downloadFile": "Скачать файл",
"downloadFolder": "Загрузить папку",
"downloadFolder": "Скачать папку",
"downloadSelected": "Скачать выбранное"
},
"errors": {
@@ -98,15 +98,19 @@
"noDownloadAccess": "Загрузка недоступна."
},
"help": {
"click": "выбрать файл или каталог",
"functionKeys": "Функциональные Клавиши",
"mouseActions": "Действия Мыши",
"fileOperations": "Операции с Файлами",
"navigation": "Навигация",
"click": "выбрать файл или папку",
"ctrl": {
"click": "выбрать несколько файлов или каталогов",
"click": "выбрать несколько файлов или папок",
"d": "скачать выбранные элементы",
"b": "переключить боковую панель",
"comma": "перейти к настройкам",
"c": "копирование выбранных элементов",
"v": "Вставить скопированные/вырезанные элементы",
"x": "вырезать выбранные предметы"
"x": "вырезать выбранные элементы"
},
"del": "удалить выбранные элементы",
"esc": "очистить выделение и/или закрыть окно",
@@ -150,7 +154,7 @@
"passwordConfirm": "Подтверждение пароля",
"passwordsDontMatch": "Пароли не совпадают",
"submit": "Войти",
"usernameTaken": "Данное имя пользователя уже занято",
"usernameTaken": "Это имя пользователя уже занято",
"wrongCredentials": "Неверные данные",
"or": "ИЛИ",
"inProgress": "Вход в систему...",
@@ -160,7 +164,7 @@
"prompts": {
"copy": "Копировать",
"copyMessage": "Копировать в:",
"deleteMessageSingle": "Удалить этот файл/каталог?",
"deleteMessageSingle": "Удалить этот файл/папку?",
"deleteTitle": "Удалить файлы",
"displayName": "Отображаемое имя:",
"download": "Скачать файлы",
@@ -169,9 +173,9 @@
"fileInfo": "Информация о файле",
"move": "Переместить",
"moveMessage": "Переместить в:",
"newArchetype": "Создайте новую запись на основе архетипа. Файл будет создан в каталоге.",
"newDir": "Новый каталог",
"newDirMessage": "Имя нового каталога.",
"newArchetype": "Создать новую запись на основе архетипа. Файл будет создан в папке.",
"newDir": "Новая папка",
"newDirMessage": "Имя новой папки.",
"newFile": "Новый файл",
"newFileMessage": "Имя нового файла.",
"rename": "Переименовать",
@@ -196,7 +200,7 @@
"shareTheme": "Тема доступа",
"shareThemeColor": "Общий цвет темы (значение CSS)",
"shareTitle": "Название доступа",
"shareDescription": "Описание доступа",
"shareDescription": "Описание общей ссылки",
"shareLogo": "Поделиться URL-адресом логотипа",
"shareBanner": "Поделиться URL-адресом баннера",
"shareFavicon": "Поделиться URL-адресом favicon",
@@ -206,8 +210,8 @@
"renameMessageInvalid": "Файл не может содержать \"/\" или \"\\\".",
"source": "Источник{suffix}",
"deleteMessageMultiple": "Вы уверены, что хотите удалить файл(ы) {count}?",
"deleteMessageShare": "Вы уверены, что хотите удалить этот ресурс: {path} ?",
"numberDirs": "Количество каталогов{suffix}",
"deleteMessageShare": "Вы уверены, что хотите удалить эту общую ссылку: {path} ?",
"numberDirs": "Количество папок{suffix}",
"numberFiles": "Количество файлов{suffix}",
"renameMessageConflict": "Элемент с именем \"{filename}\" уже существует!",
"uploadSettingsChunked": "Максимальное количество одновременных загрузок: {maxConcurrentUpload}, размер чанка: {uploadChunkSizeMb} MB",
@@ -226,7 +230,22 @@
"sourcePath": "Источник:",
"destinationPath": "Пункт назначения:",
"closeWithActiveUploadsMessage": "Предупреждение: У вас есть активные загрузки, и закрытие окна загрузки может привести к незавершенным загрузкам. Что бы вы хотели сделать?",
"closeWithActiveUploads": "Активные загрузки"
"closeWithActiveUploads": "Активные загрузки",
"basicInfo": "Основная информация",
"directoryInfo": "Справочная информация",
"additionalInfo": "Дополнительная информация",
"hidden": "Скрытый",
"hasPreview": "Предварительный просмотр",
"checksums": "Контрольные суммы",
"hashAlgorithm": "Хеш-алгоритм",
"hashValue": "Хеш-значение",
"selectHashAlgorithm": "Выберите алгоритм хэширования",
"generate": "Создать",
"errorGeneratingHash": "Ошибка при генерации хэша",
"hashCopied": "Хэш копируется в буфер обмена",
"errorCopyingHash": "Ошибка при копировании хэша",
"token": "Токен",
"onlyOfficeId": "Идентификатор OnlyOffice"
},
"search": {
"images": "Изображения",
@@ -258,13 +277,13 @@
"admin": "Админ",
"administrator": "Администратор",
"allowCommands": "Запуск команд",
"allowEdit": "Редактирование, переименование и удаление файлов или каталогов",
"allowNew": "Создание новых файлов или каталогов",
"allowEdit": "Редактирование, переименование и удаление файлов или папок",
"allowNew": "Создание новых файлов или папок",
"allowPublish": "Публикация новых записей и страниц",
"allowSignup": "Разрешить пользователям регистрироваться",
"avoidChanges": "(оставьте поле пустым, чтобы избежать изменений)",
"branding": "Брендинг",
"brandingDirectoryPath": "Путь к каталогу брендов",
"brandingDirectoryPath": "Путь к папке с файлами брендинга",
"changePassword": "Изменение пароля",
"commandRunner": "Запуск команд",
"commandsUpdated": "Команды обновлены!",
@@ -272,7 +291,7 @@
"customStylesheet": "Свой стиль",
"defaultUserDescription": "Это настройки по умолчанию для новых пользователей.",
"disableExternalLinks": "Отключить внешние ссылки (кроме документации)",
"disableUsedDiskPercentage": "Disable used disk percentage graph",
"disableUsedDiskPercentage": "Отключить график использования диска",
"documentation": "документация",
"examples": "Примеры",
"executeOnShell": "Выполнить в командной строке",
@@ -311,7 +330,7 @@
"settingsUpdated": "Настройки применены!",
"shareManagement": "Управление расшаренными ссылками",
"shareDeleted": "Расшаренная ссылка удалена!",
"singleClick": "Открытие файлов и каталогов одним кликом",
"singleClick": "Открытие файлов и папок одним кликом",
"themes": {
"dark": "Темная",
"light": "Светлая",
@@ -332,7 +351,7 @@
"themeColor": "Цвет темы",
"listingOptions": "Параметры списка",
"emptyGlobal": "В настоящее время нет глобальных опций конфигурации, вы можете редактировать конфигурационный yaml для настройки параметров системы.",
"scopes": "Определите разрешенные источники и область действия пользователей в них",
"scopes": "Определить разрешенные источники и область действия пользователей в них",
"UserManagement": "Управление пользователями",
"tusUploads": "Загружаемые файлы",
"tusUploadsHelp": "File Browser поддерживает загрузку файлов в виде фрагментов, что позволяет создавать эффективные, надежные, возобновляемые и фрагментированные загрузки файлов даже в ненадежных сетях.",
@@ -340,7 +359,7 @@
"tusUploadsRetryCount": "Количество повторных попыток, которые необходимо выполнить, если чанк не удалось загрузить.",
"userHomeBasePath": "Базовый путь к домашним каталогам пользователей",
"userScopeGenerationPlaceholder": "Область действия будет сгенерирована автоматически",
"createUserHomeDirectory": "Создайте домашний каталог пользователя",
"createUserHomeDirectory": "Создать домашний каталог пользователя",
"api": "Ключи API",
"loginMethodDescription": "разрешенный метод входа для пользователя.",
"userNotAdmin": "Пользователь не является администратором",
@@ -352,7 +371,7 @@
"adminOptions": "Параметры пользователя администратора",
"shareDuration": "Срок действия:",
"searchOptions": "Параметры поиска",
"downloads": "Скачать",
"downloads": "Загрузки",
"systemAdmin": "Система и администрирование",
"configViewer": "Программа просмотра конфигурации",
"configViewerShowFull": "Показать полную конфигурацию",
@@ -375,7 +394,7 @@
"logout": "Выйти",
"myFiles": "Файлы",
"newFile": "Новый файл",
"newFolder": "Новый каталог",
"newFolder": "Новая папка",
"preview": "Предпросмотр",
"settings": "Настройки",
"signup": "Зарегистрироваться",
@@ -409,7 +428,7 @@
"disableThumbnails": "Отключить миниатюры",
"enableAllowedUsernames": "Предоставить доступ только определенным пользователям",
"allowedUsernamesPlaceholder": "Введите имена пользователей, разделенные запятыми",
"keepAfterExpiration": "Не удаляйте ресурс после истечения срока его действия",
"keepAfterExpiration": "Не удалять ресурс после истечения срока его действия",
"keepAfterExpirationDescription": "После истечения срока действия ресурс не будет удален. Это полезно, если вы хотите продлить срок действия ресурса или отредактировать его после истечения срока действия.",
"saveDisabled": "Невозможно сохранить изменения в общих файлах.",
"shareDurationDescription": "Длительность до истечения срока действия доступа. Оставьте пустым для постоянного доступа.",
@@ -425,7 +444,7 @@
"hideNavButtonsDescription": "Спрячьте кнопки навигации на навигационной панели в ресурсе, чтобы создать минималистичный вид.",
"viewModeDescription": "Макет по умолчанию для общей страницы.",
"descriptionDefault": "Вам отправлена акция для просмотра или загрузки.",
"disableShareCard": "Отключение карты доступа",
"disableShareCard": "Отключить карту доступа",
"disableShareCardDescription": "Отключите карточку общего доступа на странице общего доступа в боковой панели или в верхней части страницы на мобильных устройствах.",
"disableSidebar": "Отключить боковую панель",
"disableSidebarDescription": "Отключите боковую панель на общей странице.",
@@ -463,10 +482,10 @@
"api": {
"title": "Ключи API",
"keyName": "Имя ключа API:",
"createdAt": "Создан в:",
"expiresAt": "Истекает в:",
"createdAt": "Создан:",
"expiresAt": "Истекает:",
"permissions": "Разрешения:",
"createTitle": "Создайте ключ API",
"createTitle": "Создать ключ API",
"keyNamePlaceholder": "Введите уникальное имя ключа API:",
"tokenDuration": "Длительность токена:",
"durationNumberPlaceholder": "Номер",
@@ -490,10 +509,10 @@
"lastScanned": "Последнее сканирование",
"quickScan": "Секунды быстрого сканирования",
"fullScan": "Секунды полного сканирования",
"settingsHover": "Позьзовательские настройки",
"settingsHover": "Пользовательские настройки",
"logout": "Выход из системы",
"toggleClick": "Переключить режим клика",
"toggleDark": "Переключить темного режима",
"toggleDark": "Переключить темный режим",
"toggleSticky": "Переключить фиксированный режим",
"used": "используется",
"noSources": "Для этого пользователя нет доступных источников. Либо добавьте источник для этого пользователя, либо настройте источник с параметром defaultEnabled: true"
@@ -506,8 +525,8 @@
"invalidCodeType": "Код проверки должен состоять из 6 английских цифр",
"enabledSuccessfully": "OTP успешно активирован",
"verificationFailed": "Верификация не удалась",
"verificationSucceed": "Проверка Успех",
"generationFailed": "Поколение не удалось"
"verificationSucceed": "Проверка успешна",
"generationFailed": "Не удалось сгенерировать код"
},
"general": {
"name": "Имя",
@@ -574,7 +593,7 @@
"previewVideos": "Показывать миниатюры видео",
"previewVideosDescription": "Показывать миниатюры видео, если отключено, будет отображаться общий значок.",
"previewMotionVideos": "Включить предварительный просмотр видео",
"previewMotionVideosDescription": "Motion preview - это анимированное всплывающее окно предварительного просмотра, которое циклически показывает кадры видео.",
"previewMotionVideosDescription": "Анимированный предпросмотр - это всплывающее окно предварительного просмотра, которое циклически показывает кадры видео.",
"highQualityPreview": "Миниатюры высокого качества",
"highQualityPreviewDescription": "Влияет только на просмотр галереи. При медленном соединении загрузка может занять больше времени.",
"editOffice": "Просмотр и редактирование офисных файлов с помощью OnlyOffice",
@@ -585,7 +604,7 @@
"disableUpdateNotifications": "Отключить показ уведомлений об обновлении",
"disableUpdateNotificationsDescription": "Отключите баннер уведомления об обновлениях, который отображается на боковой панели для пользователей-администраторов.",
"disableHideSidebar": "Оставлять боковую панель открытой при предварительном просмотре или редактировании файлов",
"disableHideSidebarDescription": "Если эта функция включена, боковая панель не будет автоматически скрываться при предварительном просмотре или редактировании файлов.",
"disableHideSidebarDescription": "Если включено, боковая панель не будет автоматически скрываться при предварительном просмотре или редактировании файлов.",
"autoplayMedia": "Автовоспроизведение медиафайлов при просмотре",
"autoplayMediaDescription": "Автовоспроизведение медиафайлов при просмотре. Это будет работать, только если файл является медиафайлом.",
"sidebarOptions": "Параметры боковой панели",
@@ -602,7 +621,7 @@
"previewOffice": "Показывать миниатюры офисных файлов",
"previewOfficeDescription": "Показывать миниатюры для офисных типов файлов в представлении списка",
"disableThumbnailPreviews": "Отключить миниатюры для определенных расширений файлов",
"disableThumbnailPreviewsDescription": "Список расширений файлов, для которых необходимо отключить предварительный просмотр миниатюр (например, '.txt .html'), разделенный пробелами.",
"disableThumbnailPreviewsDescription": "Список расширений файлов, для которых необходимо отключить миниатюры (например, '.txt .html'), разделенный пробелами.",
"disableViewingFiles": "Отключить просмотрщик/редактор файлов для определенных расширений файлов",
"disableViewingFilesDescription": "Список расширений файлов, для которых необходимо отключить просмотрщик/редактор файлов (например, '.txt .pdf'), разделенный пробелами.",
"disablePreviewExt": "Отключение предварительного просмотра офисных файлов для определенных расширений файлов",
@@ -639,7 +658,7 @@
"ShuffleAllPlayback": "Перемешать все",
"PlayAllLoopedPlayback": "Воспроизвести все с повторением",
"QueueButtonHint": "Показать очередь воспроизведения",
"QueuePlayback": "Очередь Воспроизведения",
"QueuePlayback": "Очередь воспроизведения",
"changePlaybackMode": "Изменить режим воспроизведения",
"changePlaybackModeHint": "Измените режим воспроизведения, чтобы увидеть больше файлов",
"emptyQueue": "Очередь пуста"
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Stiahnutie nie je k dispozícii."
},
"help": {
"functionKeys": "Funkčné Klávesy",
"mouseActions": "Akcie Myši",
"fileOperations": "Operácie so Súbormi",
"navigation": "Navigácia",
"click": "vyberie súbor alebo priečinok",
"ctrl": {
"click": "vyberie viac súborov alebo priečinkov",
@@ -226,7 +230,22 @@
"sourcePath": "Zdroj:",
"destinationPath": "Cieľová destinácia:",
"closeWithActiveUploadsMessage": "Varovanie: Upozornenie: Máte aktívne nahrávanie a zatvorenie výzvy na nahrávanie by mohlo viesť k nedokončenému nahrávaniu. Čo by ste chceli urobiť?",
"closeWithActiveUploads": "Aktívne nahrávanie"
"closeWithActiveUploads": "Aktívne nahrávanie",
"basicInfo": "Základné informácie",
"directoryInfo": "Informácie o adresári",
"additionalInfo": "Ďalšie informácie",
"hidden": "Skryté",
"hasPreview": "Má náhľad",
"checksums": "Kontrolné súčty",
"hashAlgorithm": "Algoritmus Hash",
"hashValue": "Hodnota Hash",
"selectHashAlgorithm": "Výber algoritmu hash",
"generate": "Generovať",
"errorGeneratingHash": "Chyba pri generovaní hash",
"hashCopied": "Hash skopírovaný do schránky",
"errorCopyingHash": "Chyba pri kopírovaní hash",
"token": "Token",
"onlyOfficeId": "IbaOffice ID"
},
"search": {
"images": "Obrázky",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Nedladdning är inte tillgänglig."
},
"help": {
"functionKeys": "Funktionstangenter",
"mouseActions": "Musåtgärder",
"fileOperations": "Filoperationer",
"navigation": "Navigering",
"click": "välj fil eller mapp",
"ctrl": {
"click": "välj flera filer eller mappar",
@@ -226,7 +230,22 @@
"sourcePath": "Källa:",
"destinationPath": "Destination:",
"closeWithActiveUploadsMessage": "Varning för uppladdning: Du har aktiva uppladdningar och om du stänger uppladdningsprompten kan det leda till oavslutade uppladdningar. Vad skulle du vilja göra?",
"closeWithActiveUploads": "Aktiva uppladdningar"
"closeWithActiveUploads": "Aktiva uppladdningar",
"basicInfo": "Grundläggande information",
"directoryInfo": "Kataloginformation",
"additionalInfo": "Ytterligare information",
"hidden": "Dolda",
"hasPreview": "Har förhandsgranskning",
"checksums": "Kontrollsummor",
"hashAlgorithm": "Hash-algoritm",
"hashValue": "Hash-värde",
"selectHashAlgorithm": "Välj en hashalgoritm",
"generate": "Generera",
"errorGeneratingHash": "Fel vid generering av hash",
"hashCopied": "Hash kopieras till urklipp",
"errorCopyingHash": "Fel vid kopiering av hash",
"token": "Token",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Bilder",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "İndirme mevcut değil."
},
"help": {
"functionKeys": "Fonksiyon Tuşları",
"mouseActions": "Fare İşlemleri",
"fileOperations": "Dosya İşlemleri",
"navigation": "Gezinme",
"click": "dosya veya klasör seçin",
"ctrl": {
"click": "çoklu dosya ve klasör seçin",
@@ -226,7 +230,22 @@
"sourcePath": "Kaynak:",
"destinationPath": "Varış yeri:",
"closeWithActiveUploadsMessage": "Uyarı: Aktif yüklemeleriniz var ve yükleme istemini kapatmak tamamlanmamış yüklemelere neden olabilir. Ne yapmak istiyorsunuz?",
"closeWithActiveUploads": "Aktif yüklemeler"
"closeWithActiveUploads": "Aktif yüklemeler",
"basicInfo": "Temel Bilgiler",
"directoryInfo": "Dizin Bilgileri",
"additionalInfo": "Ek Bilgi",
"hidden": "Gizli",
"hasPreview": "Has Önizleme",
"checksums": "Checksumlar",
"hashAlgorithm": "Hash Algoritması",
"hashValue": "Hash Değeri",
"selectHashAlgorithm": "Bir karma algoritma seçin",
"generate": "Oluşturmak",
"errorGeneratingHash": "Hash oluştururken hata oluştu",
"hashCopied": "Panoya kopyalanan karma",
"errorCopyingHash": "Karma kopyalama hatası",
"token": "Jeton",
"onlyOfficeId": "SadeceOfis Kimliği"
},
"search": {
"images": "Görseller",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "Завантаження недоступне."
},
"help": {
"functionKeys": "Функціональні Клавіші",
"mouseActions": "Дії Миші",
"fileOperations": "Операції з Файлами",
"navigation": "Навігація",
"click": "вибрати файл чи каталог",
"ctrl": {
"click": "вибрати кілька файлів чи каталогів",
@@ -226,7 +230,22 @@
"sourcePath": "Джерело:",
"destinationPath": "Пункт призначення:",
"closeWithActiveUploadsMessage": "Попередження: У вас є активні завантаження, і закриття запиту на завантаження може призвести до незавершених завантажень. Що ви хочете зробити?",
"closeWithActiveUploads": "Активні завантаження"
"closeWithActiveUploads": "Активні завантаження",
"basicInfo": "Основна інформація",
"directoryInfo": "Інформація про каталог",
"additionalInfo": "Додаткова інформація",
"hidden": "Приховано",
"hasPreview": "Має попередній перегляд",
"checksums": "Контрольні суми",
"hashAlgorithm": "Алгоритм хешування",
"hashValue": "Хеш-значення",
"selectHashAlgorithm": "Виберіть алгоритм хешування",
"generate": "Згенерувати",
"errorGeneratingHash": "Хеш, що генерує помилки",
"hashCopied": "Хеш скопійовано до буфера обміну",
"errorCopyingHash": "Помилка копіювання хешу",
"token": "Токен.",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "Зображення",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "无法下载。"
},
"help": {
"functionKeys": "功能键",
"mouseActions": "鼠标操作",
"fileOperations": "文件操作",
"navigation": "导航",
"click": "选择文件或目录",
"ctrl": {
"click": "选择多个文件或目录",
@@ -226,7 +230,22 @@
"sourcePath": "资料来源",
"destinationPath": "目的地",
"closeWithActiveUploadsMessage": "警告:您正在上传,关闭上传提示可能会导致上传未完成。您想做什么?",
"closeWithActiveUploads": "主动上传"
"closeWithActiveUploads": "主动上传",
"basicInfo": "基本信息",
"directoryInfo": "目录信息",
"additionalInfo": "其他信息",
"hidden": "隐藏",
"hasPreview": "预览",
"checksums": "校验和",
"hashAlgorithm": "哈希算法",
"hashValue": "哈希值",
"selectHashAlgorithm": "选择散列算法",
"generate": "生成",
"errorGeneratingHash": "错误生成哈希值",
"hashCopied": "哈希值复制到剪贴板",
"errorCopyingHash": "复制哈希值出错",
"token": "代币",
"onlyOfficeId": "唯一办公室 ID"
},
"search": {
"images": "图像",
+20 -1
View File
@@ -98,6 +98,10 @@
"noDownloadAccess": "無法下載。"
},
"help": {
"functionKeys": "功能鍵",
"mouseActions": "滑鼠操作",
"fileOperations": "檔案操作",
"navigation": "導航",
"click": "選擇檔案或目錄",
"ctrl": {
"click": "選擇多個檔案或目錄",
@@ -226,7 +230,22 @@
"sourcePath": "來源",
"destinationPath": "目的地:",
"closeWithActiveUploadsMessage": "警告:您有進行中的上傳,關閉上傳提示可能會導致未完成的上傳。您想做什麼?",
"closeWithActiveUploads": "有效上傳"
"closeWithActiveUploads": "有效上傳",
"basicInfo": "基本資訊",
"directoryInfo": "目錄資訊",
"additionalInfo": "其他資訊",
"hidden": "隱藏",
"hasPreview": "已預覽",
"checksums": "校驗和",
"hashAlgorithm": "切細值演算法",
"hashValue": "雜湊值",
"selectHashAlgorithm": "選擇散列演算法",
"generate": "產生",
"errorGeneratingHash": "錯誤產生切細值",
"hashCopied": "Hash 複製到剪貼簿",
"errorCopyingHash": "複製散列出錯",
"token": "代幣",
"onlyOfficeId": "OnlyOffice ID"
},
"search": {
"images": "影像",
+11
View File
@@ -139,6 +139,16 @@ export function startSSE () {
setupSSE()
}
export function startOnlyOfficeSSE () {
// Reset authentication failure flag when starting SSE
authenticationFailed = false
setupSSE()
}
export function stopSSE () {
cleanup()
}
async function eventRouter (eventType, message) {
switch (eventType) {
case 'notification':
@@ -180,3 +190,4 @@ async function eventRouter (eventType, message) {
console.log('Unknown SSE event:', eventType, message)
}
}
+13 -4
View File
@@ -61,12 +61,21 @@ export const getters = {
if (!state.user || state.user?.username == "") {
return "normal";
}
const userViewmode = getters.displayPreference()?.viewMode || state.user.viewMode
// If user is anonymous and on a share, check for defaultViewMode override
if (state.user?.username === 'anonymous' && !userViewmode) {
const isShare = getters.isShare();
const displayPref = getters.displayPreference();
// Priority 1: If there's a saved display preference for this specific share/path, use it
if (displayPref?.viewMode) {
return displayPref.viewMode;
}
// Priority 2: If it's a share and shareInfo.viewMode is set, use that as the default
if (isShare && shareInfo.viewMode) {
return shareInfo.viewMode;
}
return userViewmode || "normal";
// Priority 3: Use user's default viewMode
return state.user.viewMode || "normal";
},
sorting: () => {
return getters.displayPreference()?.sorting || state.user?.sorting || { by: "name", asc: true };
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div>
<div class="error-message">
<h2 class="message">
<i class="material-icons">{{ info.icon }}</i>
<span>{{ $t(info.message) }}</span>
+20 -5
View File
@@ -17,6 +17,7 @@ import { state, getters, mutations } from "@/store";
import { removeLastDir } from "@/utils/url";
import { filesApi } from "@/api";
import { toStandardLocale } from "@/i18n";
import { events } from "@/notify";
const wikiLink = "https://github.com/gtsteffaniak/filebrowser/wiki/Office-Support#onlyoffice-integration-troubleshooting-guide"
const wikiLinkText = "📖 View Troubleshooting Guide"
@@ -134,6 +135,12 @@ export default {
// Clean up global SSE event listener
window.removeEventListener('onlyOfficeLogEvent', this.handleOnlyOfficeLogEvent);
// Clean up SSE connection if it was started for OnlyOffice admin users
if (state.user.permissions.admin && !state.user.permissions.realtime) {
console.log('🔌 Cleaning up OnlyOffice SSE connection');
events.stopSSE();
}
},
methods: {
getInternalUrlInfo() {
@@ -287,6 +294,8 @@ export default {
`;
}
const noLogsMessage = !state.user.permissions.admin ? "Backend logs are not available -- user must be admin to view backend logs" : "Waiting for backend logs...";
let content = `
<div class="debug-tooltip">
<div class="debug-header">
@@ -329,7 +338,7 @@ export default {
</div>`
).join('')}
</div>
` : 'Backend logs are not available -- user must be admin to view backend logs'}
` : noLogsMessage}
${overallStatus}
</div>
@@ -725,7 +734,13 @@ export default {
if (!state.user.permissions.admin && !this.debugMode) {
return;
}
// Start SSE connection for admin users even if they don't have realtime permissions
if (state.user.permissions.admin && !state.user.permissions.realtime) {
console.log('🔗 Starting SSE connection for OnlyOffice admin user');
events.startOnlyOfficeSSE();
}
// Setup the global SSE listener (documentId will be set later if not available yet)
this.setupGlobalSSEListener();
},
@@ -734,7 +749,7 @@ export default {
setupGlobalSSEListener() {
// Bind the event handler to this component instance
this.handleOnlyOfficeLogEvent = this.handleOnlyOfficeLogEvent.bind(this);
// Listen for custom events that we'll dispatch from the global SSE system
window.addEventListener('onlyOfficeLogEvent', this.handleOnlyOfficeLogEvent);
},
@@ -742,13 +757,13 @@ export default {
// Handle OnlyOffice log events from global SSE system
handleOnlyOfficeLogEvent(event) {
const logData = event.detail;
// If documentId is not set yet, store the log for later (this can happen during early setup)
if (!this.documentId) {
this.addOnlyOfficeLog(logData);
return;
}
// Filter logs for this document
if (logData.documentId === this.documentId) {
this.addOnlyOfficeLog(logData);
+12 -3
View File
@@ -91,7 +91,13 @@ export default {
return state.user.permissions;
},
showImage() {
return this.previewType == 'image' || this.pdfConvertable || this.heicConvertable;
if (state.req.type == "image/heic" || state.req.type == "image/heif") {
if (this.isHeicAndViewable) {
return true;
}
return false;
}
return this.previewType == 'image' || this.pdfConvertable;
},
autoPlay() {
return state.user.preview.autoplayMedia;
@@ -106,8 +112,11 @@ export default {
const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
return isIOS && isSafari;
},
heicConvertable() {
return globalVars.enableHeicConversion && state.req.type == "image/heic";
isHeicAndViewable() {
if (globalVars.enableHeicConversion || state.isSafari) {
return true;
}
return false;
},
pdfConvertable() {
if (!globalVars.muPdfAvailable) {
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
@@ -9,7 +9,7 @@ test("info from listing", async({ page, checkForErrors, context }) => {
await page.locator('.selected-count-header').waitFor({ state: 'visible' });
await expect(page.locator('.selected-count-header')).toHaveText('1');
await page.locator('button[aria-label="Info"]').click();
await expect(page.locator('.break-word')).toHaveText('Display Name: file.tar.gz');
await expect(page.locator('span[aria-label="info display name"]')).toHaveText('file.tar.gz');
checkForErrors();
});
@@ -23,7 +23,7 @@ test("info from search", async({ page, checkForErrors, context }) => {
await page.locator('.selected-count-header').waitFor({ state: 'visible' });
await expect(page.locator('.selected-count-header')).toHaveText('1');
await page.locator('button[aria-label="Info"]').click();
await expect(page.locator('.break-word')).toHaveText('Display Name: file.tar.gz');
await expect(page.locator('span[aria-label="info display name"]')).toHaveText('file.tar.gz');
checkForErrors();
})
@@ -64,7 +64,7 @@ test("info from search", async ({ page, checkForErrors, context, theme }) => {
await expect(page.locator('.selected-count-header')).toHaveText('1');
await page.screenshot({ path: `./screenshots/search/right-click-${theme}.jpg`, quality: jpgQuality });
await page.locator('button[aria-label="Info"]').click();
await expect(page.locator('.break-word')).toHaveText('Display Name: file.tar.gz');
await expect(page.locator('span[aria-label="info display name"]')).toHaveText('Display Name: file.tar.gz');
await page.waitForTimeout(500);
await page.screenshot({ path: `./screenshots/file-no-preview/file.tar.gz-${theme}.jpg`, quality: jpgQuality });
})
@@ -9,7 +9,7 @@ test("info from listing", async({ page, checkForErrors, context }) => {
await page.locator('.selected-count-header').waitFor({ state: 'visible' });
await expect(page.locator('.selected-count-header')).toHaveText('1');
await page.locator('button[aria-label="Info"]').click();
await expect(page.locator('.break-word')).toHaveText('Display Name: file.tar.gz');
await expect(page.locator('span[aria-label="info display name"]')).toHaveText('file.tar.gz');
checkForErrors();
});
@@ -23,7 +23,7 @@ test("info from search", async({ page, checkForErrors, context }) => {
await page.locator('.selected-count-header').waitFor({ state: 'visible' });
await expect(page.locator('.selected-count-header')).toHaveText('1');
await page.locator('button[aria-label="Info"]').click();
await expect(page.locator('.break-word')).toHaveText('Display Name: file.tar.gz');
await expect(page.locator('span[aria-label="info display name"]')).toHaveText('file.tar.gz');
checkForErrors();
})
@@ -18,7 +18,7 @@ test("navigate folder -- item should be visible", async ({ page, checkForErrors,
await expect(page.locator('a[aria-label="excludedButVisible"]')).toHaveCount(1);
await page.goto("/files/exclude/excludedButVisible");
await expect(page.locator('a[aria-label="shouldshow.txt"]')).toHaveCount(1);
checkForErrors(); // expect error not indexed
checkForErrors();
});
test("navigate subfolderExclusions -- item should be visible", async ({ page, checkForErrors, context }) => {
@@ -28,7 +28,7 @@ test("navigate subfolderExclusions -- item should be visible", async ({ page, ch
await expect(page.locator('a[aria-label="subfolderExclusions"]')).toHaveCount(1);
await page.goto("/files/include/subfolderExclusions");
await expect(page.locator('a[aria-label="shouldshow"]')).toHaveCount(1);
checkForErrors(); // expect error not indexed
checkForErrors();
});
test("navigate subfolderExclusions -- subfolder items rules should be applied", async ({ page, checkForErrors, context }) => {
@@ -45,6 +45,21 @@ test("navigate subfolderExclusions -- subfolder items rules should be applied",
await expect(page.locator('a[aria-label="startsWithFolder"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="startsWithTest.txt"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="exclusionlist.sh"]')).toHaveCount(0);
await expect(page.locator('a[aria-label=".hiddenDir"]')).toHaveCount(0);
await expect(page.locator('a[aria-label=".hidden"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="fileName"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="folderName"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="fileNames"]')).toHaveCount(0);
await expect(page.locator('a[aria-label="folderNames"]')).toHaveCount(0);
checkForErrors(); // expect error not indexed
checkForErrors();
});
test("navigate subfolderExclusions -- nested subfolder items rules should inherit from parent", async ({ page, checkForErrors, context }) => {
await page.goto("/files/include/subfolderExclusions/.hiddenDir/nested.txt");
await expect(page).toHaveTitle("Graham's Filebrowser - Files");
await expect(page.locator('.error-message .message > span')).toHaveText('Something really went wrong.');
checkForErrors(1,1); // expect error not indexed
});