Localization - Part 2 (#2178)
* Changed language codes in the UI to be a list of all codes we will ever support. * Converted actionables * Fixed the GetLocales not using Intersect, but Union. * Fixed some localization strings in backend when user doesn't exist. Removed AllowAnonymous from reset-password, since it is a protected API * Fixed all instances of anonymous APIs where Claim wouldn't work * Keyed preference options and mixed misc localization issues * Translations update from Hosted Weblate (#2177) * Bump versions by dotnet-bump-version. * Added translation using Weblate (Dutch) * Bump versions by dotnet-bump-version. * Translated using Weblate (Dutch) Currently translated at 20.8% (33 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Translated using Weblate (Spanish) Currently translated at 1.4% (20 of 1371 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/es/ * Translated using Weblate (Dutch) Currently translated at 60.1% (95 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Translated using Weblate (Dutch) Currently translated at 60.1% (95 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Added translation using Weblate (Dutch) --------- Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com> Co-authored-by: Javier Barbero <javier.agustin.barbero@gmail.com> Co-authored-by: Stijn <stijn.biemans@gmail.com> --------- Co-authored-by: Weblate (bot) <hosted@weblate.org> Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com> Co-authored-by: Javier Barbero <javier.agustin.barbero@gmail.com> Co-authored-by: Stijn <stijn.biemans@gmail.com>
This commit is contained in:
parent
c7701bc729
commit
69532d45ac
26 changed files with 2035 additions and 195 deletions
|
|
@ -71,7 +71,6 @@ public class AccountController : BaseApiController
|
|||
/// </summary>
|
||||
/// <param name="resetPasswordDto"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost("reset-password")]
|
||||
public async Task<ActionResult> UpdatePassword(ResetPasswordDto resetPasswordDto)
|
||||
{
|
||||
|
|
@ -119,7 +118,7 @@ public class AccountController : BaseApiController
|
|||
public async Task<ActionResult<UserDto>> RegisterFirstUser(RegisterDto registerDto)
|
||||
{
|
||||
var admins = await _userManager.GetUsersInRoleAsync("Admin");
|
||||
if (admins.Count > 0) return BadRequest(await _localizationService.Translate(User.GetUserId(), "denied"));
|
||||
if (admins.Count > 0) return BadRequest(await _localizationService.Get("en", "denied"));
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -137,8 +136,8 @@ public class AccountController : BaseApiController
|
|||
if (!result.Succeeded) return BadRequest(result.Errors);
|
||||
|
||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
if (string.IsNullOrEmpty(token)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "confirm-token-gen"));
|
||||
if (!await ConfirmEmailToken(token, user)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "validate-email", token));
|
||||
if (string.IsNullOrEmpty(token)) return BadRequest(await _localizationService.Get("en", "confirm-token-gen"));
|
||||
if (!await ConfirmEmailToken(token, user)) return BadRequest(await _localizationService.Get("en", "validate-email", token));
|
||||
|
||||
|
||||
var roleResult = await _userManager.AddToRoleAsync(user, PolicyConstants.AdminRole);
|
||||
|
|
@ -165,7 +164,7 @@ public class AccountController : BaseApiController
|
|||
await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "register-user"));
|
||||
return BadRequest(await _localizationService.Get("en", "register-user"));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -182,9 +181,9 @@ public class AccountController : BaseApiController
|
|||
.Include(u => u.UserPreferences)
|
||||
.SingleOrDefaultAsync(x => x.NormalizedUserName == loginDto.Username.ToUpper());
|
||||
|
||||
if (user == null) return Unauthorized(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
if (user == null) return Unauthorized(await _localizationService.Get("en", "bad-credentials"));
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
if (!roles.Contains(PolicyConstants.LoginRole)) return Unauthorized(await _localizationService.Translate(User.GetUserId(), "disabled-account"));
|
||||
if (!roles.Contains(PolicyConstants.LoginRole)) return Unauthorized(await _localizationService.Translate(user.Id, "disabled-account"));
|
||||
|
||||
var result = await _signInManager
|
||||
.CheckPasswordSignInAsync(user, loginDto.Password, true);
|
||||
|
|
@ -192,12 +191,12 @@ public class AccountController : BaseApiController
|
|||
if (result.IsLockedOut)
|
||||
{
|
||||
await _userManager.UpdateSecurityStampAsync(user);
|
||||
return Unauthorized(await _localizationService.Translate(User.GetUserId(), "locked-out"));
|
||||
return Unauthorized(await _localizationService.Translate(user.Id, "locked-out"));
|
||||
}
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return Unauthorized(await _localizationService.Translate(User.GetUserId(), result.IsNotAllowed ? "confirm-email" : "bad-credentials"));
|
||||
return Unauthorized(await _localizationService.Translate(user.Id, result.IsNotAllowed ? "confirm-email" : "bad-credentials"));
|
||||
}
|
||||
|
||||
// Update LastActive on account
|
||||
|
|
@ -258,7 +257,7 @@ public class AccountController : BaseApiController
|
|||
var token = await _tokenService.ValidateRefreshToken(tokenRequestDto);
|
||||
if (token == null)
|
||||
{
|
||||
return Unauthorized(new { message = await _localizationService.Translate(User.GetUserId(), "invalid-token") });
|
||||
return Unauthorized(new { message = await _localizationService.Get("en", "invalid-token") });
|
||||
}
|
||||
|
||||
return Ok(token);
|
||||
|
|
@ -670,7 +669,7 @@ public class AccountController : BaseApiController
|
|||
if (user == null)
|
||||
{
|
||||
_logger.LogInformation("confirm-email failed from invalid registered email: {Email}", dto.Email);
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-email-confirmation"));
|
||||
return BadRequest(await _localizationService.Get("en", "invalid-email-confirmation"));
|
||||
}
|
||||
|
||||
// Validate Password and Username
|
||||
|
|
@ -691,7 +690,7 @@ public class AccountController : BaseApiController
|
|||
if (!await ConfirmEmailToken(dto.Token, user))
|
||||
{
|
||||
_logger.LogInformation("confirm-email failed from invalid token: {Token}", dto.Token);
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-email-confirmation"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "invalid-email-confirmation"));
|
||||
}
|
||||
|
||||
user.UserName = dto.Username;
|
||||
|
|
@ -734,13 +733,13 @@ public class AccountController : BaseApiController
|
|||
if (user == null)
|
||||
{
|
||||
_logger.LogInformation("confirm-email failed from invalid registered email: {Email}", dto.Email);
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-email-confirmation"));
|
||||
return BadRequest(await _localizationService.Get("en", "invalid-email-confirmation"));
|
||||
}
|
||||
|
||||
if (!await ConfirmEmailToken(dto.Token, user))
|
||||
{
|
||||
_logger.LogInformation("confirm-email failed from invalid token: {Token}", dto.Token);
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-email-confirmation"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "invalid-email-confirmation"));
|
||||
}
|
||||
|
||||
_logger.LogInformation("User is updating email from {OldEmail} to {NewEmail}", user.Email, dto.Email);
|
||||
|
|
@ -748,7 +747,7 @@ public class AccountController : BaseApiController
|
|||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("Unable to update email for users: {Errors}", result.Errors.Select(e => e.Description));
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-user-email-update"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "generic-user-email-update"));
|
||||
}
|
||||
user.ConfirmationToken = null;
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
|
@ -766,12 +765,12 @@ public class AccountController : BaseApiController
|
|||
[HttpPost("confirm-password-reset")]
|
||||
public async Task<ActionResult<string>> ConfirmForgotPassword(ConfirmPasswordResetDto dto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
try
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null)
|
||||
{
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
return BadRequest(await _localizationService.Get("en", "bad-credentials"));
|
||||
}
|
||||
|
||||
var result = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider,
|
||||
|
|
@ -779,16 +778,16 @@ public class AccountController : BaseApiController
|
|||
if (!result)
|
||||
{
|
||||
_logger.LogInformation("Unable to reset password, your email token is not correct: {@Dto}", dto);
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "bad-credentials"));
|
||||
}
|
||||
|
||||
var errors = await _accountService.ChangeUserPassword(user, dto.Password);
|
||||
return errors.Any() ? BadRequest(errors) : Ok(await _localizationService.Translate(User.GetUserId(), "password-updated"));
|
||||
return errors.Any() ? BadRequest(errors) : Ok(await _localizationService.Translate(user.Id, "password-updated"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "There was an unexpected error when confirming new password");
|
||||
return BadRequest("generic-password-update");
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "generic-password-update"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -807,15 +806,15 @@ public class AccountController : BaseApiController
|
|||
if (user == null)
|
||||
{
|
||||
_logger.LogError("There are no users with email: {Email} but user is requesting password reset", email);
|
||||
return Ok(await _localizationService.Translate(User.GetUserId(), "forgot-password-generic"));
|
||||
return Ok(await _localizationService.Get("en", "forgot-password-generic"));
|
||||
}
|
||||
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
if (!roles.Any(r => r is PolicyConstants.AdminRole or PolicyConstants.ChangePasswordRole))
|
||||
return Unauthorized(await _localizationService.Translate(User.GetUserId(), "permission-denied"));
|
||||
return Unauthorized(await _localizationService.Translate(user.Id, "permission-denied"));
|
||||
|
||||
if (string.IsNullOrEmpty(user.Email) || !user.EmailConfirmed)
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "confirm-email"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "confirm-email"));
|
||||
|
||||
var token = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
var emailLink = await _accountService.GenerateEmailLink(Request, token, "confirm-reset-password", user.Email);
|
||||
|
|
@ -828,10 +827,10 @@ public class AccountController : BaseApiController
|
|||
ServerConfirmationLink = emailLink,
|
||||
InstallId = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.InstallId)).Value
|
||||
});
|
||||
return Ok(await _localizationService.Translate(User.GetUserId(), "email-sent"));
|
||||
return Ok(await _localizationService.Translate(user.Id, "email-sent"));
|
||||
}
|
||||
|
||||
return Ok(await _localizationService.Translate(User.GetUserId(), "not-accessible-password"));
|
||||
return Ok(await _localizationService.Translate(user.Id, "not-accessible-password"));
|
||||
}
|
||||
|
||||
[HttpGet("email-confirmed")]
|
||||
|
|
@ -848,12 +847,12 @@ public class AccountController : BaseApiController
|
|||
public async Task<ActionResult<UserDto>> ConfirmMigrationEmail(ConfirmMigrationEmailDto dto)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (user == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
if (user == null) return BadRequest(await _localizationService.Get("en", "bad-credentials"));
|
||||
|
||||
if (!await ConfirmEmailToken(dto.Token, user))
|
||||
{
|
||||
_logger.LogInformation("confirm-migration-email email token is invalid");
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "bad-credentials"));
|
||||
}
|
||||
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
|
@ -884,12 +883,12 @@ public class AccountController : BaseApiController
|
|||
public async Task<ActionResult<string>> ResendConfirmationSendEmail([FromQuery] int userId)
|
||||
{
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
|
||||
if (user == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-user"));
|
||||
if (user == null) return BadRequest(await _localizationService.Get("en", "no-user"));
|
||||
|
||||
if (string.IsNullOrEmpty(user.Email))
|
||||
return BadRequest(
|
||||
await _localizationService.Translate(User.GetUserId(), "user-migration-needed"));
|
||||
if (user.EmailConfirmed) return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-confirmed"));
|
||||
await _localizationService.Translate(user.Id, "user-migration-needed"));
|
||||
if (user.EmailConfirmed) return BadRequest(await _localizationService.Translate(user.Id, "user-already-confirmed"));
|
||||
|
||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var emailLink = await _accountService.GenerateEmailLink(Request, token, "confirm-email", user.Email);
|
||||
|
|
@ -910,12 +909,12 @@ public class AccountController : BaseApiController
|
|||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "There was an issue resending invite email");
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-invite-email"));
|
||||
return BadRequest(await _localizationService.Translate(user.Id, "generic-invite-email"));
|
||||
}
|
||||
return Ok(emailLink);
|
||||
}
|
||||
|
||||
return Ok(await _localizationService.Translate(User.GetUserId(), "not-accessible"));
|
||||
return Ok(await _localizationService.Translate(user.Id, "not-accessible"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -929,7 +928,7 @@ public class AccountController : BaseApiController
|
|||
{
|
||||
// If there is an admin account already, return
|
||||
var users = await _unitOfWork.UserRepository.GetAdminUsersAsync();
|
||||
if (users.Any()) return BadRequest(await _localizationService.Translate(User.GetUserId(), "admin-already-exists"));
|
||||
if (users.Any()) return BadRequest(await _localizationService.Get("en", "admin-already-exists"));
|
||||
|
||||
// Check if there is an existing invite
|
||||
var emailValidationErrors = await _accountService.ValidateEmail(dto.Email);
|
||||
|
|
@ -937,27 +936,27 @@ public class AccountController : BaseApiController
|
|||
{
|
||||
var invitedUser = await _unitOfWork.UserRepository.GetUserByEmailAsync(dto.Email);
|
||||
if (await _userManager.IsEmailConfirmedAsync(invitedUser!))
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-registered", invitedUser!.UserName));
|
||||
return BadRequest(await _localizationService.Get("en", "user-already-registered", invitedUser!.UserName));
|
||||
|
||||
_logger.LogInformation("A user is attempting to login, but hasn't accepted email invite");
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "user-already-invited"));
|
||||
return BadRequest(await _localizationService.Get("en", "user-already-invited"));
|
||||
}
|
||||
|
||||
|
||||
var user = await _userManager.Users
|
||||
.Include(u => u.UserPreferences)
|
||||
.SingleOrDefaultAsync(x => x.NormalizedUserName == dto.Username.ToUpper());
|
||||
if (user == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-username"));
|
||||
if (user == null) return BadRequest(await _localizationService.Get("en", "invalid-username"));
|
||||
|
||||
var validPassword = await _signInManager.UserManager.CheckPasswordAsync(user, dto.Password);
|
||||
if (!validPassword) return BadRequest(await _localizationService.Translate(User.GetUserId(), "bad-credentials"));
|
||||
if (!validPassword) return BadRequest(await _localizationService.Get("en", "bad-credentials"));
|
||||
|
||||
try
|
||||
{
|
||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
|
||||
user.Email = dto.Email;
|
||||
if (!await ConfirmEmailToken(token, user)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "critical-email-migration"));
|
||||
if (!await ConfirmEmailToken(token, user)) return BadRequest(await _localizationService.Get("en", "critical-email-migration"));
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
|
@ -971,7 +970,7 @@ public class AccountController : BaseApiController
|
|||
await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "critical-email-migration"));
|
||||
return BadRequest(await _localizationService.Get("en", "critical-email-migration"));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -981,8 +980,6 @@ public class AccountController : BaseApiController
|
|||
var result = await _userManager.ConfirmEmailAsync(user, token);
|
||||
if (result.Succeeded) return true;
|
||||
|
||||
|
||||
|
||||
_logger.LogCritical("[Account] Email validation failed");
|
||||
if (!result.Errors.Any()) return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -96,14 +96,14 @@ public class BookController : BaseApiController
|
|||
[AllowAnonymous]
|
||||
public async Task<ActionResult> GetBookPageResources(int chapterId, [FromQuery] string file)
|
||||
{
|
||||
if (chapterId <= 0) return BadRequest(await _localizationService.Translate(User.GetUserId(), "chapter-doesnt-exist"));
|
||||
if (chapterId <= 0) return BadRequest(await _localizationService.Get("en", "chapter-doesnt-exist"));
|
||||
var chapter = await _unitOfWork.ChapterRepository.GetChapterAsync(chapterId);
|
||||
if (chapter == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "chapter-doesnt-exist"));
|
||||
if (chapter == null) return BadRequest(await _localizationService.Get("en", "chapter-doesnt-exist"));
|
||||
using var book = await EpubReader.OpenBookAsync(chapter.Files.ElementAt(0).FilePath, BookService.BookReaderOptions);
|
||||
|
||||
var key = BookService.CoalesceKeyForAnyFile(book, file);
|
||||
|
||||
if (!book.Content.AllFiles.ContainsLocalFileRefWithKey(key)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "file-missing"));
|
||||
if (!book.Content.AllFiles.ContainsLocalFileRefWithKey(key)) return BadRequest(await _localizationService.Get("en", "file-missing"));
|
||||
|
||||
var bookFile = book.Content.AllFiles.GetLocalFileRefByKey(key);
|
||||
var content = await bookFile.ReadContentAsBytesAsync();
|
||||
|
|
|
|||
|
|
@ -43,9 +43,10 @@ public class ImageController : BaseApiController
|
|||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"chapterId", "apiKey"})]
|
||||
public async Task<ActionResult> GetChapterCoverImage(int chapterId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.ChapterRepository.GetChapterCoverImageAsync(chapterId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
var format = _directoryService.FileSystem.Path.GetExtension(path);
|
||||
|
||||
return PhysicalFile(path, MimeTypeMap.GetMimeType(format), _directoryService.FileSystem.Path.GetFileName(path));
|
||||
|
|
@ -60,9 +61,10 @@ public class ImageController : BaseApiController
|
|||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"libraryId", "apiKey"})]
|
||||
public async Task<ActionResult> GetLibraryCoverImage(int libraryId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.LibraryRepository.GetLibraryCoverImageAsync(libraryId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
var format = _directoryService.FileSystem.Path.GetExtension(path);
|
||||
|
||||
return PhysicalFile(path, MimeTypeMap.GetMimeType(format), _directoryService.FileSystem.Path.GetFileName(path));
|
||||
|
|
@ -77,9 +79,10 @@ public class ImageController : BaseApiController
|
|||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"volumeId", "apiKey"})]
|
||||
public async Task<ActionResult> GetVolumeCoverImage(int volumeId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.VolumeRepository.GetVolumeCoverImageAsync(volumeId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
var format = _directoryService.FileSystem.Path.GetExtension(path);
|
||||
|
||||
return PhysicalFile(path, MimeTypeMap.GetMimeType(format), _directoryService.FileSystem.Path.GetFileName(path));
|
||||
|
|
@ -94,9 +97,10 @@ public class ImageController : BaseApiController
|
|||
[HttpGet("series-cover")]
|
||||
public async Task<ActionResult> GetSeriesCoverImage(int seriesId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.SeriesRepository.GetSeriesCoverImageAsync(seriesId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
var format = _directoryService.FileSystem.Path.GetExtension(path);
|
||||
|
||||
Response.AddCacheHeader(path);
|
||||
|
|
@ -113,13 +117,15 @@ public class ImageController : BaseApiController
|
|||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"collectionTagId", "apiKey"})]
|
||||
public async Task<ActionResult> GetCollectionCoverImage(int collectionTagId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.CollectionTagRepository.GetCoverImageAsync(collectionTagId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path))
|
||||
{
|
||||
var destFile = await GenerateCollectionCoverImage(collectionTagId);
|
||||
if (string.IsNullOrEmpty(destFile)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
return PhysicalFile(destFile, MimeTypeMap.GetMimeType(_directoryService.FileSystem.Path.GetExtension(destFile)), _directoryService.FileSystem.Path.GetFileName(destFile));
|
||||
if (string.IsNullOrEmpty(destFile)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
return PhysicalFile(destFile, MimeTypeMap.GetMimeType(_directoryService.FileSystem.Path.GetExtension(destFile)),
|
||||
_directoryService.FileSystem.Path.GetFileName(destFile));
|
||||
}
|
||||
var format = _directoryService.FileSystem.Path.GetExtension(path);
|
||||
|
||||
|
|
@ -135,12 +141,13 @@ public class ImageController : BaseApiController
|
|||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"readingListId", "apiKey"})]
|
||||
public async Task<ActionResult> GetReadingListCoverImage(int readingListId, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.ReadingListRepository.GetCoverImageAsync(readingListId));
|
||||
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path))
|
||||
{
|
||||
var destFile = await GenerateReadingListCoverImage(readingListId);
|
||||
if (string.IsNullOrEmpty(destFile)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-cover-image"));
|
||||
if (string.IsNullOrEmpty(destFile)) return BadRequest(await _localizationService.Translate(userId, "no-cover-image"));
|
||||
return PhysicalFile(destFile, MimeTypeMap.GetMimeType(_directoryService.FileSystem.Path.GetExtension(destFile)), _directoryService.FileSystem.Path.GetFileName(destFile));
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +209,7 @@ public class ImageController : BaseApiController
|
|||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var bookmark = await _unitOfWork.UserRepository.GetBookmarkForPage(pageNum, chapterId, userId);
|
||||
if (bookmark == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "bookmark-doesnt-exist"));
|
||||
if (bookmark == null) return BadRequest(await _localizationService.Translate(userId, "bookmark-doesnt-exist"));
|
||||
|
||||
var bookmarkDirectory =
|
||||
(await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.BookmarkDirectory)).Value;
|
||||
|
|
@ -223,7 +230,7 @@ public class ImageController : BaseApiController
|
|||
{
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
if (string.IsNullOrEmpty(url)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "must-be-defined", "Url"));
|
||||
if (string.IsNullOrEmpty(url)) return BadRequest(await _localizationService.Translate(userId, "must-be-defined", "Url"));
|
||||
var encodeFormat = (await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EncodeMediaAs;
|
||||
|
||||
// Check if the domain exists
|
||||
|
|
@ -238,7 +245,7 @@ public class ImageController : BaseApiController
|
|||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "generic-favicon"));
|
||||
return BadRequest(await _localizationService.Translate(userId, "generic-favicon"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ public class LibraryController : BaseApiController
|
|||
var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
|
||||
if (!isAdmin) return BadRequest("API key must belong to an admin");
|
||||
|
||||
if (dto.FolderPath.Contains("..")) return BadRequest(await _localizationService.Translate(User.GetUserId(), "invalid-path"));
|
||||
if (dto.FolderPath.Contains("..")) return BadRequest(await _localizationService.Translate(user.Id, "invalid-path"));
|
||||
|
||||
dto.FolderPath = Services.Tasks.Scanner.Parser.Parser.NormalizePath(dto.FolderPath);
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,8 @@ public class ReaderController : BaseApiController
|
|||
public async Task<ActionResult> GetImage(int chapterId, int page, string apiKey, bool extractPdf = false)
|
||||
{
|
||||
if (page < 0) page = 0;
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var chapter = await _cacheService.Ensure(chapterId, extractPdf);
|
||||
if (chapter == null) return NoContent();
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ public class ReaderController : BaseApiController
|
|||
{
|
||||
var path = _cacheService.GetCachedPagePath(chapter.Id, page);
|
||||
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-image-for-page", page));
|
||||
return BadRequest(await _localizationService.Translate(userId, "no-image-for-page", page));
|
||||
var format = Path.GetExtension(path);
|
||||
|
||||
return PhysicalFile(path, MimeTypeMap.GetMimeType(format), Path.GetFileName(path), true);
|
||||
|
|
@ -139,7 +140,8 @@ public class ReaderController : BaseApiController
|
|||
[AllowAnonymous]
|
||||
public async Task<ActionResult> GetThumbnail(int chapterId, int pageNum, string apiKey)
|
||||
{
|
||||
if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
if (userId == 0) return BadRequest();
|
||||
var chapter = await _cacheService.Ensure(chapterId, true);
|
||||
if (chapter == null) return NoContent();
|
||||
var images = _cacheService.GetCachedPages(chapterId);
|
||||
|
|
@ -175,7 +177,7 @@ public class ReaderController : BaseApiController
|
|||
try
|
||||
{
|
||||
var path = _cacheService.GetCachedBookmarkPagePath(seriesId, page);
|
||||
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "no-image-for-page", page));
|
||||
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path)) return BadRequest(await _localizationService.Translate(userId, "no-image-for-page", page));
|
||||
var format = Path.GetExtension(path);
|
||||
|
||||
return PhysicalFile(path, MimeTypeMap.GetMimeType(format), Path.GetFileName(path));
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public class ThemeController : BaseApiController
|
|||
}
|
||||
catch (KavitaException ex)
|
||||
{
|
||||
return BadRequest(await _localizationService.Translate(User.GetUserId(), ex.Message));
|
||||
return BadRequest(await _localizationService.Get("en", ex.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
104
API/I18N/nl.json
104
API/I18N/nl.json
|
|
@ -1 +1,103 @@
|
|||
{}
|
||||
{
|
||||
"password-updated": "Wachtwoord bijgewerkt",
|
||||
"user-already-registered": "Gebruiker is al geregistreerd als {0}",
|
||||
"generic-invite-user": "Er is een probleem opgetreden bij het uitnodigen van de gebruiker. Controleer de logboeken.",
|
||||
"generate-token": "Er is een probleem opgetreden bij het genereren van een bevestigings- e-mailtoken. Zie logboek",
|
||||
"generic-user-email-update": "E-mail voor gebruiker kan niet worden bijgewerkt. Controleer de logboeken.",
|
||||
"generic-password-update": "Er is een onverwachte fout opgetreden bij het bevestigen van het nieuwe wachtwoord",
|
||||
"locked-out": "U bent uitgesloten door te veel autorisatiepogingen. Wacht alsjeblieft 10 minuten.",
|
||||
"register-user": "Er is iets misgegaan bij het registreren van de gebruiker",
|
||||
"bad-credentials": "Uw inloggegevens zijn niet correct",
|
||||
"disabled-account": "Uw account is uitgeschakeld. Neem contact op met de serverbeheerder.",
|
||||
"validate-email": "Er is een probleem opgetreden bij het valideren van uw e-mailadres: {0}",
|
||||
"confirm-token-gen": "Er is een probleem opgetreden bij het genereren van een bevestigingstoken",
|
||||
"denied": "Niet toegestaan",
|
||||
"invalid-password": "Ongeldig wachtwoord",
|
||||
"invalid-token": "Ongeldige Token",
|
||||
"unable-to-reset-key": "Er is iets misgegaan, kan de sleutel niet resetten",
|
||||
"invalid-payload": "Ongeldige lading",
|
||||
"nothing-to-do": "Niets te doen",
|
||||
"share-multiple-emails": "U kunt geen e-mailadressen delen met meerdere accounts",
|
||||
"age-restriction-update": "Er is een fout opgetreden bij het updaten van de leeftijdsbeperking",
|
||||
"no-user": "Gebruiker bestaat niet",
|
||||
"username-taken": "Gebruikersnaam al in gebruik",
|
||||
"user-already-confirmed": "Gebruiker is al bevestigd",
|
||||
"manual-setup-fail": "Handmatige aanmaak kan niet worden voltooid. Annuleer en maak de uitnodiging opnieuw",
|
||||
"user-already-invited": "Gebruiker is al uitgenodigd onder dit e-mailadres en moet de uitnodiging nog accepteren.",
|
||||
"invalid-email-confirmation": "Ongeldige e-mailbevestiging",
|
||||
"forgot-password-generic": "Er wordt een e-mail verzonden naar het e-mailadres als deze in onze database voorkomt",
|
||||
"not-accessible-password": "Uw server is niet toegankelijk. De link om je wachtwoord te resetten staat in het logboek",
|
||||
"not-accessible": "Uw server is niet extern toegankelijk",
|
||||
"email-sent": "Email verzonden",
|
||||
"confirm-email": "U moet eerst uw e-mail bevestigen",
|
||||
"permission-denied": "U heeft geen toestemming voor deze operatie",
|
||||
"password-required": "U moet uw bestaande wachtwoord invoeren om uw account te wijzigen, tenzij u een beheerder bent",
|
||||
"generic-reading-list-delete": "Er is een probleem opgetreden bij het verwijderen van de leeslijst",
|
||||
"reading-list-deleted": "Leeslijst is verwijderd",
|
||||
"reading-list-doesnt-exist": "Leeslijst bestaat niet",
|
||||
"generic-relationship": "Er is een probleem opgetreden bij het updaten van relaties",
|
||||
"no-series-collection": "Kan series niet ophalen van collectie",
|
||||
"generic-series-delete": "Er is een probleem opgetreden bij het verwijderen van de serie",
|
||||
"series-updated": "Succesvol geüpdatet",
|
||||
"update-metadata-fail": "Kan metadata niet updaten",
|
||||
"generic-series-update": "Er is een fout opgetreden bij het updaten van de serie",
|
||||
"age-restriction-not-applicable": "Geen beperkingen",
|
||||
"job-already-running": "Taak loopt al",
|
||||
"greater-0": "{0} moet groter zijn dan 0",
|
||||
"send-to-kavita-email": "Verzenden naar apparaat kan niet worden gebruikt met de e-mailservice van Kavita. Configureer uw eigen.",
|
||||
"send-to-device-status": "Bestanden overzetten naar uw apparaat",
|
||||
"generic-send-to": "Er is een fout opgetreden bij het verzenden van de bestanden naar het apparaat",
|
||||
"volume-doesnt-exist": "Volume bestaat niet",
|
||||
"series-doesnt-exist": "Serie bestaat niet",
|
||||
"bookmarks-empty": "Bladwijzers kunnen niet leeg zijn",
|
||||
"reading-list-updated": "Bijgewerkt",
|
||||
"user-migration-needed": "Deze gebruiker moet migreren. Laat ze uitloggen en inloggen om de migratie op gang te brengen",
|
||||
"generic-invite-email": "Er is een probleem opgetreden bij het opnieuw verzenden van de uitnodigingsmail",
|
||||
"admin-already-exists": "Beheerder bestaat al",
|
||||
"invalid-username": "Ongeldige gebruikersnaam",
|
||||
"critical-email-migration": "Er is een probleem opgetreden tijdens de e-mailmigratie. Neem contact op met de ondersteuning",
|
||||
"chapter-doesnt-exist": "Hoofdstuk bestaat niet",
|
||||
"file-missing": "Bestand is niet gevonden in boek",
|
||||
"collection-updated": "Verzameling succesvol bijgewerkt",
|
||||
"generic-error": "Er is iets mis gegaan, probeer het alstublieft nogmaals",
|
||||
"collection-doesnt-exist": "Collectie bestaat niet",
|
||||
"device-doesnt-exist": "Apparaat bestaat niet",
|
||||
"generic-device-create": "Er is een fout opgetreden bij het maken van het apparaat",
|
||||
"generic-device-update": "Er is een fout opgetreden bij het updaten van het apparaat",
|
||||
"generic-device-delete": "Er is een fout opgetreden bij het verwijderen van het apparaat",
|
||||
"no-cover-image": "Geen omslagafbeelding",
|
||||
"bookmark-doesnt-exist": "Bladwijzer bestaat niet",
|
||||
"must-be-defined": "{0} moet gedefinieerd zijn",
|
||||
"generic-favicon": "Er is een probleem opgetreden bij het ophalen van de favicon voor het domein",
|
||||
"invalid-filename": "Ongeldige bestandsnaam",
|
||||
"file-doesnt-exist": "Bestand bestaat niet",
|
||||
"library-name-exists": "Bibliotheeknaam bestaat al. Kies een unieke naam voor de server.",
|
||||
"generic-library": "Er was een kritiek probleem. Probeer het opnieuw.",
|
||||
"no-library-access": "Gebruiker heeft geen toegang tot deze bibliotheek",
|
||||
"user-doesnt-exist": "Gebruiker bestaat niet",
|
||||
"library-doesnt-exist": "Bibliotheek bestaat niet",
|
||||
"invalid-path": "Ongeldig pad",
|
||||
"delete-library-while-scan": "U kunt een bibliotheek niet verwijderen terwijl er een scan wordt uitgevoerd. Wacht tot de scan is voltooid of herstart Kavita en probeer het vervolgens te verwijderen",
|
||||
"generic-library-update": "Er is een kritiek probleem opgetreden bij het updaten van de bibliotheek.",
|
||||
"pdf-doesnt-exist": "PDF bestaat niet wanneer het zou moeten",
|
||||
"invalid-access": "Ongeldige toegang",
|
||||
"no-image-for-page": "Zo'n afbeelding ontbreekt voor pagina {0}. Probeer te vernieuwen om opnieuw cachen mogelijk te maken.",
|
||||
"perform-scan": "Voer een scan uit op deze serie of bibliotheek en probeer het opnieuw",
|
||||
"generic-read-progress": "Er is een probleem opgetreden bij het opslaan van de voortgang",
|
||||
"generic-clear-bookmarks": "Kan bladwijzers niet wissen",
|
||||
"bookmark-permission": "U heeft geen toestemming om een bladwijzer te maken/de bladwijzer ongedaan te maken",
|
||||
"bookmark-save": "Kan bladwijzer niet opslaan",
|
||||
"cache-file-find": "Kan afbeelding in cache niet vinden. Laad opnieuw en probeer het opnieuw.",
|
||||
"name-required": "Naam mag niet leeg zijn",
|
||||
"valid-number": "Moet een geldig paginanummer zijn",
|
||||
"duplicate-bookmark": "Dubbele bladwijzervermelding bestaat al",
|
||||
"reading-list-permission": "U heeft geen rechten voor deze leeslijst of de lijst bestaat niet",
|
||||
"reading-list-position": "Kan positie niet updaten",
|
||||
"reading-list-item-delete": "Kan item(s) niet verwijderen",
|
||||
"generic-reading-list-update": "Er is een probleem opgetreden bij het updaten van de leeslijst",
|
||||
"generic-reading-list-create": "Er is een probleem opgetreden bij het maken van de leeslijst",
|
||||
"series-restricted": "Gebruiker heeft geen toegang tot deze serie",
|
||||
"libraries-restricted": "Gebruiker heeft geen toegang tot de bibliotheken",
|
||||
"no-series": "Kan series van bibliotheek niet ophalen",
|
||||
"generic-user-update": "Er was een uitzondering bij het updaten van de gebruiker"
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ public class LocalizationService : ILocalizationService
|
|||
{
|
||||
_localizationDirectoryUi = directoryService.FileSystem.Path.Join(
|
||||
directoryService.FileSystem.Directory.GetCurrentDirectory(),
|
||||
"UI/Web/src/assets/langs");
|
||||
"../UI/Web/src/assets/langs");
|
||||
} else if (environment.EnvironmentName.Equals("Testing", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_localizationDirectoryUi = directoryService.FileSystem.Path.Join(
|
||||
|
|
@ -136,11 +136,12 @@ public class LocalizationService : ILocalizationService
|
|||
/// <returns></returns>
|
||||
public IEnumerable<string> GetLocales()
|
||||
{
|
||||
return
|
||||
_directoryService.GetFilesWithExtension(_directoryService.FileSystem.Path.GetFullPath(_localizationDirectoryUi), @"\.json")
|
||||
.Select(f => _directoryService.FileSystem.Path.GetFileName(f).Replace(".json", string.Empty))
|
||||
.Union(_directoryService.GetFilesWithExtension(_directoryService.LocalizationDirectory, @"\.json")
|
||||
.Select(f => _directoryService.FileSystem.Path.GetFileName(f).Replace(".json", string.Empty)))
|
||||
.Distinct();
|
||||
var uiLanguages = _directoryService
|
||||
.GetFilesWithExtension(_directoryService.FileSystem.Path.GetFullPath(_localizationDirectoryUi), @"\.json")
|
||||
.Select(f => _directoryService.FileSystem.Path.GetFileName(f).Replace(".json", string.Empty));
|
||||
var backendLanguages = _directoryService
|
||||
.GetFilesWithExtension(_directoryService.LocalizationDirectory, @"\.json")
|
||||
.Select(f => _directoryService.FileSystem.Path.GetFileName(f).Replace(".json", string.Empty));
|
||||
return uiLanguages.Intersect(backendLanguages).Distinct();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ public class ThemeService : IThemeService
|
|||
/// </summary>
|
||||
/// <param name="themeId"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
public async Task<string> GetContent(int themeId)
|
||||
{
|
||||
var theme = await _unitOfWork.SiteThemeRepository.GetThemeDto(themeId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue