001/* 002 * Copyright 2017-2022 Product Mog LLC, 2022-2026 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.lokalized; 018 019import org.jspecify.annotations.NonNull; 020import org.jspecify.annotations.Nullable; 021 022import javax.annotation.concurrent.NotThreadSafe; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.Locale; 026import java.util.Map; 027 028import static java.util.Objects.requireNonNull; 029 030/** 031 * Exception thrown when no translation is found when {@link com.lokalized.DefaultStrings.FailureMode} is configured to be {@link com.lokalized.DefaultStrings.FailureMode#FAIL_FAST}. 032 * <p> 033 * In production, you would normally prefer {@link com.lokalized.DefaultStrings.FailureMode#USE_FALLBACK}. 034 * <p> 035 * This class is intended for use by a single thread. 036 * 037 * @author <a href="https://revetkn.com">Mark Allen</a> 038 */ 039@NotThreadSafe 040public class MissingTranslationException extends RuntimeException { 041 @NonNull 042 private final String key; 043 @NonNull 044 private final Locale locale; 045 @NonNull 046 private final Map<@NonNull String, @Nullable Object> placeholders; 047 048 /** 049 * Constructs a new exception with the unsupported locale. 050 * 051 * @param locale the unsupported locale which triggered this exception, not null 052 */ 053 public MissingTranslationException(@NonNull String message, 054 @NonNull String key, 055 @NonNull Map<@NonNull String, @Nullable Object> placeholders, 056 @NonNull Locale locale) { 057 super(requireNonNull(message)); 058 059 requireNonNull(key); 060 requireNonNull(placeholders); 061 requireNonNull(locale); 062 063 this.key = key; 064 this.placeholders = Collections.unmodifiableMap(new HashMap<>(placeholders)); 065 this.locale = locale; 066 } 067 068 /** 069 * The translation key that triggered this exception. 070 * 071 * @return the translation key, not null 072 */ 073 @NonNull 074 public String getKey() { 075 return this.key; 076 } 077 078 /** 079 * The placeholders specified for the failed translation attempt. 080 * 081 * @return the placeholders, not null 082 */ 083 @NonNull 084 public Map<@NonNull String, @Nullable Object> getPlaceholders() { 085 return this.placeholders; 086 } 087 088 /** 089 * The locale that triggered this exception. 090 * 091 * @return the locale, not null 092 */ 093 @NonNull 094 public Locale getLocale() { 095 return this.locale; 096 } 097}